cryptol 2.13.0 → 3.0.0
raw patch · 105 files changed
+10640/−3132 lines, 105 filesdep +Win32dep +criterion-measurementdep +hgmpdep ~ghc-bignumdep ~sbvdep ~what4PVP ok
version bump matches the API change (PVP)
Dependencies added: Win32, criterion-measurement, hgmp, language-c99, language-c99-simple, libffi, pretty, pretty-show, unix, vector
Dependency ranges changed: ghc-bignum, sbv, what4
API changes (from Hackage documentation)
- Cryptol.Backend: type family SEval sym :: Type -> Type;
- Cryptol.Eval.Value: type family SEval sym :: Type -> Type;
- Cryptol.ModuleSystem: FailedToParameterizeModDefs :: ModName -> [Name] -> ModuleError
- Cryptol.ModuleSystem: IfaceParams :: Map Name ModTParam -> [Located Prop] -> Map Name ModVParam -> IfaceParams
- Cryptol.ModuleSystem: ImportedParamModule :: ModName -> ModuleError
- Cryptol.ModuleSystem: NotAParameterizedModule :: ModName -> ModuleError
- Cryptol.ModuleSystem: [ifModName] :: IfaceG mname -> !mname
- Cryptol.ModuleSystem: [ifParamConstraints] :: IfaceParams -> [Located Prop]
- Cryptol.ModuleSystem: [ifParamFuns] :: IfaceParams -> Map Name ModVParam
- Cryptol.ModuleSystem: [ifParamTypes] :: IfaceParams -> Map Name ModTParam
- Cryptol.ModuleSystem: [ifPrivate] :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem: [ifPublic] :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem: data IfaceParams
- Cryptol.ModuleSystem: type IfaceTySyn = TySyn
- Cryptol.ModuleSystem.Base: checkSingleModule :: Act (Module Name) Module -> ImportSource -> Module PName -> ModuleM (NamingEnv, Module)
- Cryptol.ModuleSystem.Env: [lmFingerprint] :: LoadedModule -> Fingerprint
- Cryptol.ModuleSystem.Env: [lmInterface] :: LoadedModule -> Iface
- Cryptol.ModuleSystem.Env: [lmModule] :: LoadedModule -> Module
- Cryptol.ModuleSystem.Env: data LoadedModule
- Cryptol.ModuleSystem.Env: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Env.LoadedModule
- Cryptol.ModuleSystem.Env: instance GHC.Generics.Generic Cryptol.ModuleSystem.Env.LoadedModule
- Cryptol.ModuleSystem.Env: instance GHC.Show.Show Cryptol.ModuleSystem.Env.LoadedModule
- Cryptol.ModuleSystem.Exports: modExports :: Ord name => ModuleG mname name -> ExportSpec name
- Cryptol.ModuleSystem.Exports: names :: (a -> ([Located a'], b)) -> TopLevel a -> [TopLevel a']
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Defines Cryptol.TypeCheck.AST.Decl
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Defines Cryptol.TypeCheck.AST.DeclGroup
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Defines t => Cryptol.ModuleSystem.InstantiateModule.Defines [t]
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst (Cryptol.ModuleSystem.Exports.ExportSpec Cryptol.ModuleSystem.Name.Name)
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.AST.Decl
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.AST.DeclDef
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.AST.DeclGroup
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.AST.Expr
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.AST.Match
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.TCon.TC
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.TCon.TCon
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.TCon.UserTC
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.Type.AbstractType
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.Type.Newtype
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.Type.Schema
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.Type.TySyn
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst Cryptol.TypeCheck.Type.Type
- Cryptol.ModuleSystem.InstantiateModule: instance Cryptol.ModuleSystem.InstantiateModule.Inst a => Cryptol.ModuleSystem.InstantiateModule.Inst [a]
- Cryptol.ModuleSystem.InstantiateModule: instance GHC.Show.Show Cryptol.ModuleSystem.InstantiateModule.Env
- Cryptol.ModuleSystem.InstantiateModule: instantiateModule :: FreshM m => Module -> ModName -> Map TParam Type -> Map Name Expr -> m (Name -> Name, [Located Prop], Module)
- Cryptol.ModuleSystem.Interface: IfaceParams :: Map Name ModTParam -> [Located Prop] -> Map Name ModVParam -> IfaceParams
- Cryptol.ModuleSystem.Interface: [ifModName] :: IfaceG mname -> !mname
- Cryptol.ModuleSystem.Interface: [ifParamConstraints] :: IfaceParams -> [Located Prop]
- Cryptol.ModuleSystem.Interface: [ifParamFuns] :: IfaceParams -> Map Name ModVParam
- Cryptol.ModuleSystem.Interface: [ifParamTypes] :: IfaceParams -> Map Name ModTParam
- Cryptol.ModuleSystem.Interface: [ifPrivate] :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem.Interface: [ifPublic] :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem.Interface: data IfaceParams
- Cryptol.ModuleSystem.Interface: flatPublicDecls :: IfaceDecls -> IfaceDecls
- Cryptol.ModuleSystem.Interface: flatPublicIface :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem.Interface: ifTySynName :: TySyn -> Name
- Cryptol.ModuleSystem.Interface: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Interface.IfaceParams
- Cryptol.ModuleSystem.Interface: instance Control.DeepSeq.NFData mname => Control.DeepSeq.NFData (Cryptol.ModuleSystem.Interface.IfaceG mname)
- Cryptol.ModuleSystem.Interface: instance GHC.Generics.Generic (Cryptol.ModuleSystem.Interface.IfaceG mname)
- Cryptol.ModuleSystem.Interface: instance GHC.Generics.Generic Cryptol.ModuleSystem.Interface.IfaceParams
- Cryptol.ModuleSystem.Interface: instance GHC.Show.Show Cryptol.ModuleSystem.Interface.IfaceParams
- Cryptol.ModuleSystem.Interface: instance GHC.Show.Show mname => GHC.Show.Show (Cryptol.ModuleSystem.Interface.IfaceG mname)
- Cryptol.ModuleSystem.Interface: isEmptyIfaceParams :: IfaceParams -> Bool
- Cryptol.ModuleSystem.Interface: noIfaceParams :: IfaceParams
- Cryptol.ModuleSystem.Interface: type IfaceNewtype = Newtype
- Cryptol.ModuleSystem.Interface: type IfaceTySyn = TySyn
- Cryptol.ModuleSystem.Monad: FailedToParameterizeModDefs :: ModName -> [Name] -> ModuleError
- Cryptol.ModuleSystem.Monad: ImportedParamModule :: ModName -> ModuleError
- Cryptol.ModuleSystem.Monad: NotAParameterizedModule :: ModName -> ModuleError
- Cryptol.ModuleSystem.Monad: failedToParameterizeModDefs :: ModName -> [Name] -> ModuleM a
- Cryptol.ModuleSystem.Monad: getIface :: ModName -> ModuleM Iface
- Cryptol.ModuleSystem.Monad: importParamModule :: ModName -> ModuleM a
- Cryptol.ModuleSystem.Monad: notAParameterizedModule :: ModName -> ModuleM a
- Cryptol.ModuleSystem.Name: Declared :: !ModPath -> !NameSource -> NameInfo
- Cryptol.ModuleSystem.Name: Parameter :: NameInfo
- Cryptol.ModuleSystem.Name: asParamName :: Name -> Name
- Cryptol.ModuleSystem.Name: instance GHC.Classes.Eq Cryptol.ModuleSystem.Name.NameInfo
- Cryptol.ModuleSystem.Name: mkParameter :: Namespace -> Ident -> Range -> Supply -> (Name, Supply)
- Cryptol.ModuleSystem.Name: paramModRecParam :: Name
- Cryptol.ModuleSystem.Name: toParamInstName :: Name -> Name
- Cryptol.ModuleSystem.NamingEnv: BuildNamingEnv :: SupplyT Id NamingEnv -> BuildNamingEnv
- Cryptol.ModuleSystem.NamingEnv: ImportIface :: Import -> Iface -> ImportIface
- Cryptol.ModuleSystem.NamingEnv: InModule :: Maybe ModPath -> a -> InModule a
- Cryptol.ModuleSystem.NamingEnv: [runBuild] :: BuildNamingEnv -> SupplyT Id NamingEnv
- Cryptol.ModuleSystem.NamingEnv: buildNamingEnv :: BuildNamingEnv -> Supply -> (NamingEnv, Supply)
- Cryptol.ModuleSystem.NamingEnv: class BindsNames a
- Cryptol.ModuleSystem.NamingEnv: collectNestedModules :: NamingEnv -> Module PName -> Supply -> (NestedMods, Supply)
- Cryptol.ModuleSystem.NamingEnv: collectNestedModulesDecls :: NamingEnv -> ModName -> [TopDecl PName] -> Supply -> (NestedMods, Supply)
- Cryptol.ModuleSystem.NamingEnv: collectNestedModulesDs :: ModPath -> NamingEnv -> [TopDecl PName] -> CollectM ()
- Cryptol.ModuleSystem.NamingEnv: data ImportIface
- Cryptol.ModuleSystem.NamingEnv: data InModule a
- Cryptol.ModuleSystem.NamingEnv: defsOf :: BindsNames a => a -> Supply -> (NamingEnv, Supply)
- Cryptol.ModuleSystem.NamingEnv: filterNames :: (PName -> Bool) -> NamingEnv -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.ModuleSystem.NamingEnv.InModule (Cryptol.Parser.AST.Bind Cryptol.Parser.Name.PName))
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.ModuleSystem.NamingEnv.InModule (Cryptol.Parser.AST.Decl Cryptol.Parser.Name.PName))
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.ModuleSystem.NamingEnv.InModule (Cryptol.Parser.AST.NestedModule Cryptol.Parser.Name.PName))
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.ModuleSystem.NamingEnv.InModule (Cryptol.Parser.AST.Newtype Cryptol.Parser.Name.PName))
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.ModuleSystem.NamingEnv.InModule (Cryptol.Parser.AST.ParameterFun Cryptol.Parser.Name.PName))
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.ModuleSystem.NamingEnv.InModule (Cryptol.Parser.AST.ParameterType Cryptol.Parser.Name.PName))
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.ModuleSystem.NamingEnv.InModule (Cryptol.Parser.AST.PrimType Cryptol.Parser.Name.PName))
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.ModuleSystem.NamingEnv.InModule (Cryptol.Parser.AST.TopDecl Cryptol.Parser.Name.PName))
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.Parser.AST.Module Cryptol.Parser.Name.PName)
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.Parser.AST.Schema Cryptol.Parser.Name.PName)
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames (Cryptol.Parser.AST.TParam Cryptol.Parser.Name.PName)
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames Cryptol.ModuleSystem.NamingEnv.ImportIface
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames Cryptol.ModuleSystem.NamingEnv.NamingEnv
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames a => Cryptol.ModuleSystem.NamingEnv.BindsNames (GHC.Maybe.Maybe a)
- Cryptol.ModuleSystem.NamingEnv: instance Cryptol.ModuleSystem.NamingEnv.BindsNames a => Cryptol.ModuleSystem.NamingEnv.BindsNames [a]
- Cryptol.ModuleSystem.NamingEnv: instance Data.Foldable.Foldable Cryptol.ModuleSystem.NamingEnv.InModule
- Cryptol.ModuleSystem.NamingEnv: instance Data.Traversable.Traversable Cryptol.ModuleSystem.NamingEnv.InModule
- Cryptol.ModuleSystem.NamingEnv: instance GHC.Base.Functor Cryptol.ModuleSystem.NamingEnv.InModule
- Cryptol.ModuleSystem.NamingEnv: instance GHC.Base.Monoid Cryptol.ModuleSystem.NamingEnv.BuildNamingEnv
- Cryptol.ModuleSystem.NamingEnv: instance GHC.Base.Semigroup Cryptol.ModuleSystem.NamingEnv.BuildNamingEnv
- Cryptol.ModuleSystem.NamingEnv: instance GHC.Show.Show a => GHC.Show.Show (Cryptol.ModuleSystem.NamingEnv.InModule a)
- Cryptol.ModuleSystem.NamingEnv: interpImportIface :: Import -> IfaceDecls -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: lookupTypeNames :: PName -> NamingEnv -> [Name]
- Cryptol.ModuleSystem.NamingEnv: lookupValNames :: PName -> NamingEnv -> [Name]
- Cryptol.ModuleSystem.NamingEnv: merge :: [Name] -> [Name] -> [Name]
- Cryptol.ModuleSystem.NamingEnv: moduleDefs :: ModPath -> ModuleG mname PName -> BuildNamingEnv
- Cryptol.ModuleSystem.NamingEnv: namingEnv :: BindsNames a => a -> BuildNamingEnv
- Cryptol.ModuleSystem.NamingEnv: namingEnvRename :: (Name -> Name) -> NamingEnv -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: newLocal :: FreshM m => Namespace -> PName -> Range -> m Name
- Cryptol.ModuleSystem.NamingEnv: newTop :: FreshM m => Namespace -> ModPath -> PName -> Maybe Fixity -> Range -> m Name
- Cryptol.ModuleSystem.NamingEnv: newtype BuildNamingEnv
- Cryptol.ModuleSystem.NamingEnv: singletonE :: PName -> Name -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: singletonT :: PName -> Name -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: type CollectM = StateT NestedMods (SupplyT Id)
- Cryptol.ModuleSystem.NamingEnv: type NestedMods = Map Name NamingEnv
- Cryptol.ModuleSystem.Renamer: BoundReservedType :: PName -> Maybe Range -> Doc -> RenamerError
- Cryptol.ModuleSystem.Renamer: InvalidConstraint :: Type PName -> RenamerError
- Cryptol.ModuleSystem.Renamer: MalformedBuiltin :: Type PName -> PName -> RenamerError
- Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename (Cryptol.ModuleSystem.Renamer.WithMods Cryptol.Parser.AST.NestedModule)
- Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename (Cryptol.ModuleSystem.Renamer.WithMods Cryptol.Parser.AST.TopDecl)
- Cryptol.ModuleSystem.Renamer: namingEnv :: BindsNames a => a -> BuildNamingEnv
- Cryptol.ModuleSystem.Renamer.Error: BoundReservedType :: PName -> Maybe Range -> Doc -> RenamerError
- Cryptol.ModuleSystem.Renamer.Error: InvalidConstraint :: Type PName -> RenamerError
- Cryptol.ModuleSystem.Renamer.Error: MalformedBuiltin :: Type PName -> PName -> RenamerError
- Cryptol.ModuleSystem.Renamer.Monad: [roIfaces] :: RO -> ModName -> Iface
- Cryptol.ModuleSystem.Renamer.Monad: checkEnv :: EnvCheck -> NamingEnv -> NamingEnv -> RW -> (NamingEnv, RW)
- Cryptol.ModuleSystem.Renamer.Monad: containsOverlap :: [Name] -> Seq RenamerError
- Cryptol.ModuleSystem.Renamer.Monad: lookupImport :: Import -> RenameM IfaceDecls
- Cryptol.ModuleSystem.Renamer.Monad: record :: RenamerError -> RenameM ()
- Cryptol.Parser.AST: EComplement :: Expr n -> Expr n
- Cryptol.Parser.AST: ENeg :: Expr n -> Expr n
- Cryptol.Parser.AST: [mDecls] :: ModuleG mname name -> [TopDecl name]
- Cryptol.Parser.AST: [mInstance] :: ModuleG mname name -> !Maybe (Located ModName)
- Cryptol.Parser.AST: instance GHC.Classes.Eq mname => GHC.Classes.Eq (Cryptol.Parser.AST.ImportG mname)
- Cryptol.Parser.AST: mSubmoduleImports :: ModuleG mname name -> [Located (ImportG name)]
- Cryptol.Parser.Lexer: KW_extern :: TokenKW
- Cryptol.Parser.Token: KW_extern :: TokenKW
- Cryptol.Transform.AddModParams: addModParams :: Module -> Either [Name] Module
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.AddParams Cryptol.TypeCheck.AST.Decl
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.AddParams Cryptol.TypeCheck.AST.DeclGroup
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.AddParams Cryptol.TypeCheck.AST.Expr
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.AddParams Cryptol.TypeCheck.Type.Newtype
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.AddParams Cryptol.TypeCheck.Type.Schema
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.AddParams Cryptol.TypeCheck.Type.TySyn
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.AddParams Cryptol.TypeCheck.Type.Type
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.AddParams a => Cryptol.Transform.AddModParams.AddParams [a]
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst Cryptol.TypeCheck.AST.Decl
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst Cryptol.TypeCheck.AST.DeclDef
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst Cryptol.TypeCheck.AST.DeclGroup
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst Cryptol.TypeCheck.AST.Expr
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst Cryptol.TypeCheck.AST.Match
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst Cryptol.TypeCheck.Type.Newtype
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst Cryptol.TypeCheck.Type.TySyn
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst Cryptol.TypeCheck.Type.Type
- Cryptol.Transform.AddModParams: instance Cryptol.Transform.AddModParams.Inst a => Cryptol.Transform.AddModParams.Inst [a]
- Cryptol.TypeCheck: [inpParamConstraints] :: InferInput -> ![Located Prop]
- Cryptol.TypeCheck: [inpParamFuns] :: InferInput -> !Map Name ModVParam
- Cryptol.TypeCheck: [inpParamTypes] :: InferInput -> !Map Name ModTParam
- Cryptol.TypeCheck: tcModuleInst :: IORef NamingEnv -> Module -> Module Name -> InferInput -> IO (InferOutput Module)
- Cryptol.TypeCheck.AST: [mImports] :: ModuleG mname -> [Import]
- Cryptol.TypeCheck.AST: [mSubModules] :: ModuleG mname -> Map Name (IfaceG Name)
- Cryptol.TypeCheck.CheckModuleInstance: checkModuleInstance :: Module -> Module -> InferM (Name -> Name, Module)
- Cryptol.TypeCheck.Infer: inferModule :: Module Name -> InferM Module
- Cryptol.TypeCheck.Monad: [inpParamConstraints] :: InferInput -> ![Located Prop]
- Cryptol.TypeCheck.Monad: [inpParamFuns] :: InferInput -> !Map Name ModVParam
- Cryptol.TypeCheck.Monad: [inpParamTypes] :: InferInput -> !Map Name ModTParam
- Cryptol.TypeCheck.Monad: endModuleInstance :: InferM ()
- Cryptol.TypeCheck.Monad: getParamFuns :: InferM (Map Name ModVParam)
- Cryptol.TypeCheck.Monad: lookupParamFun :: Name -> InferM (Maybe ModVParam)
- Cryptol.TypeCheck.Monad: newParamName :: Namespace -> Ident -> InferM Name
- Cryptol.TypeCheck.Solver.SMT: instance Cryptol.TypeCheck.Solver.SMT.Mk GHC.Integer.Type.Integer
- Cryptol.TypeCheck.Subst: instance Cryptol.TypeCheck.Subst.TVars Cryptol.TypeCheck.AST.Module
- Cryptol.TypeCheck.Type: [mtpNumber] :: ModTParam -> !Int
- Cryptol.Utils.Ident: isParamInstModName :: ModName -> Bool
- Cryptol.Utils.Ident: notParamInstModName :: ModName -> ModName
- Cryptol.Utils.Ident: paramInstModName :: ModName -> ModName
+ Cryptol.Backend: type SBit sym :: Type;
+ Cryptol.Backend: type SEval sym :: Type -> Type;
+ Cryptol.Backend: type SFloat sym :: Type;
+ Cryptol.Backend: type SInteger sym :: Type;
+ Cryptol.Backend: type SWord sym :: Type;
+ Cryptol.Backend.FFI: SomeFFIArg :: a -> SomeFFIArg
+ Cryptol.Backend.FFI: callForeignImpl :: forall a. FFIRet a => ForeignImpl -> [SomeFFIArg] -> IO a
+ Cryptol.Backend.FFI: class Storable a => FFIArg a
+ Cryptol.Backend.FFI: class Storable a => FFIRet a
+ Cryptol.Backend.FFI: data ForeignImpl
+ Cryptol.Backend.FFI: data ForeignSrc
+ Cryptol.Backend.FFI: data SomeFFIArg
+ Cryptol.Backend.FFI: foreignLibPath :: FilePath -> IO (Maybe FilePath)
+ Cryptol.Backend.FFI: getForeignSrcPath :: ForeignSrc -> Maybe FilePath
+ Cryptol.Backend.FFI: instance Control.DeepSeq.NFData Cryptol.Backend.FFI.ForeignSrc
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIArg (GHC.Ptr.Ptr a)
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIArg Foreign.C.Types.CDouble
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIArg Foreign.C.Types.CFloat
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIArg Foreign.C.Types.CSize
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIArg GHC.Word.Word16
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIArg GHC.Word.Word32
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIArg GHC.Word.Word64
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIArg GHC.Word.Word8
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIRet ()
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIRet Foreign.C.Types.CDouble
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIRet Foreign.C.Types.CFloat
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIRet GHC.Word.Word16
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIRet GHC.Word.Word32
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIRet GHC.Word.Word64
+ Cryptol.Backend.FFI: instance Cryptol.Backend.FFI.FFIRet GHC.Word.Word8
+ Cryptol.Backend.FFI: instance GHC.Show.Show Cryptol.Backend.FFI.ForeignSrc
+ Cryptol.Backend.FFI: loadForeignImpl :: ForeignSrc -> String -> IO (Either FFILoadError ForeignImpl)
+ Cryptol.Backend.FFI: loadForeignSrc :: FilePath -> IO (Either FFILoadError ForeignSrc)
+ Cryptol.Backend.FFI: unloadForeignSrc :: ForeignSrc -> IO ()
+ Cryptol.Backend.FFI.Error: CantLoadFFIImpl :: String -> String -> FFILoadError
+ Cryptol.Backend.FFI.Error: CantLoadFFISrc :: FilePath -> String -> FFILoadError
+ Cryptol.Backend.FFI.Error: FFIDuplicates :: [Name] -> FFILoadError
+ Cryptol.Backend.FFI.Error: FFIInFunctor :: Name -> FFILoadError
+ Cryptol.Backend.FFI.Error: data FFILoadError
+ Cryptol.Backend.FFI.Error: instance Control.DeepSeq.NFData Cryptol.Backend.FFI.Error.FFILoadError
+ Cryptol.Backend.FFI.Error: instance Cryptol.Utils.PP.PP Cryptol.Backend.FFI.Error.FFILoadError
+ Cryptol.Backend.FFI.Error: instance GHC.Generics.Generic Cryptol.Backend.FFI.Error.FFILoadError
+ Cryptol.Backend.FFI.Error: instance GHC.Show.Show Cryptol.Backend.FFI.Error.FFILoadError
+ Cryptol.Backend.FloatHelpers: floatFromDouble :: Double -> BF
+ Cryptol.Backend.Monad: FFINotSupported :: Name -> EvalError
+ Cryptol.Backend.Monad: FFITypeNumTooBig :: Name -> TParam -> Integer -> EvalError
+ Cryptol.Backend.Monad: NoMatchingPropGuardCase :: String -> EvalError
+ Cryptol.Eval: FFINotSupported :: Name -> EvalError
+ Cryptol.Eval: FFITypeNumTooBig :: Name -> TParam -> Integer -> EvalError
+ Cryptol.Eval: NoMatchingPropGuardCase :: String -> EvalError
+ Cryptol.Eval: checkProp :: Prop -> Bool
+ Cryptol.Eval.FFI: evalForeignDecls :: ForeignSrc -> [(Name, FFIFunType)] -> EvalEnv -> Eval (Either [FFILoadError] EvalEnv)
+ Cryptol.Eval.FFI: findForeignDecls :: ModuleG mname -> [(Name, FFIFunType)]
+ Cryptol.Eval.FFI.GenHeader: generateForeignHeader :: [(Name, FFIFunType)] -> String
+ Cryptol.Eval.FFI.GenHeader: instance GHC.Classes.Eq Cryptol.Eval.FFI.GenHeader.Include
+ Cryptol.Eval.FFI.GenHeader: instance GHC.Classes.Ord Cryptol.Eval.FFI.GenHeader.Include
+ Cryptol.Eval.Type: instance GHC.Show.Show Cryptol.Eval.Type.TypeEnv
+ Cryptol.Eval.Type: tvFloat64 :: TValue
+ Cryptol.Eval.Value: type SBit sym :: Type;
+ Cryptol.Eval.Value: type SEval sym :: Type -> Type;
+ Cryptol.Eval.Value: type SFloat sym :: Type;
+ Cryptol.Eval.Value: type SInteger sym :: Type;
+ Cryptol.Eval.Value: type SWord sym :: Type;
+ Cryptol.IR.TraverseNames: class TraverseNames t
+ Cryptol.IR.TraverseNames: instance (GHC.Classes.Ord a, Cryptol.IR.TraverseNames.TraverseNames a) => Cryptol.IR.TraverseNames.TraverseNames (Cryptol.ModuleSystem.Exports.ExportSpec a)
+ Cryptol.IR.TraverseNames: instance (GHC.Classes.Ord a, Cryptol.IR.TraverseNames.TraverseNames a) => Cryptol.IR.TraverseNames.TraverseNames (Data.Set.Internal.Set a)
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.ModuleSystem.Name.Name
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.AST.Decl
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.AST.DeclDef
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.AST.DeclGroup
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.AST.Expr
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.AST.Match
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.FFI.FFIType.FFIFunType
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.FFI.FFIType.FFIType
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.TCon.TC
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.TCon.TCon
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.TCon.UserTC
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.ArgDescr
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.ModTParam
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.ModVParam
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.Newtype
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.Schema
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.TPFlavor
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.TParam
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.TVar
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.TVarInfo
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.TySyn
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.Type
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames Cryptol.TypeCheck.Type.TypeSource
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames a => Cryptol.IR.TraverseNames.TraverseNames (Cryptol.Parser.Position.Located a)
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames a => Cryptol.IR.TraverseNames.TraverseNames (GHC.Maybe.Maybe a)
+ Cryptol.IR.TraverseNames: instance Cryptol.IR.TraverseNames.TraverseNames a => Cryptol.IR.TraverseNames.TraverseNames [a]
+ Cryptol.IR.TraverseNames: mapNames :: TraverseNames t => (Name -> Name) -> t -> t
+ Cryptol.IR.TraverseNames: traverseNames :: (TraverseNames t, Applicative f) => (Name -> f Name) -> t -> f t
+ Cryptol.IR.TraverseNames: traverseNamesIP :: (TraverseNames t, Applicative f, ?name :: Name -> f Name) => t -> f t
+ Cryptol.ModuleSystem: ExpandPropGuardsError :: ImportSource -> Error -> ModuleError
+ Cryptol.ModuleSystem: FFILoadErrors :: ModName -> [FFILoadError] -> ModuleError
+ Cryptol.ModuleSystem: [ifDeclIsPrim] :: IfaceDecl -> !Bool
+ Cryptol.ModuleSystem: [ifDefines] :: IfaceG name -> IfaceDecls
+ Cryptol.ModuleSystem: [ifFunctors] :: IfaceDecls -> !Map Name (IfaceG Name)
+ Cryptol.ModuleSystem: [ifNames] :: IfaceG name -> IfaceNames name
+ Cryptol.ModuleSystem: [ifSignatures] :: IfaceDecls -> !Map Name ModParamNames
+ Cryptol.ModuleSystem: benchmarkExpr :: Double -> Expr -> ModuleCmd BenchmarkStats
+ Cryptol.ModuleSystem: checkModuleByPath :: FilePath -> ModuleCmd (ModulePath, TCTopEntity)
+ Cryptol.ModuleSystem: getFileDependencies :: FilePath -> ModuleCmd (ModulePath, FileInfo)
+ Cryptol.ModuleSystem: getModuleDependencies :: ModName -> ModuleCmd (ModulePath, FileInfo)
+ Cryptol.ModuleSystem.Base: benchmarkExpr :: Double -> Expr -> ModuleM BenchmarkStats
+ Cryptol.ModuleSystem.Base: expandPropGuards :: Module PName -> ModuleM (Module PName)
+ Cryptol.ModuleSystem.Base: findDeps :: ModuleG mname name -> [ImportSource]
+ Cryptol.ModuleSystem.Base: findDeps' :: ModuleG mname name -> (Any, Endo [ImportSource])
+ Cryptol.ModuleSystem.Base: findDepsOf :: ModulePath -> ModuleM (ModulePath, FileInfo)
+ Cryptol.ModuleSystem.Base: findDepsOfModule :: ModName -> ModuleM (ModulePath, FileInfo)
+ Cryptol.ModuleSystem.Base: findModuleDeps :: ModuleG mname name -> Set ModName
+ Cryptol.ModuleSystem.Base: tcTopEntitytLinter :: ModName -> TCLinter TCTopEntity
+ Cryptol.ModuleSystem.Binds: AFunctor :: ModKind
+ Cryptol.ModuleSystem.Binds: AModule :: ModKind
+ Cryptol.ModuleSystem.Binds: ASignature :: ModKind
+ Cryptol.ModuleSystem.Binds: InModule :: Maybe ModPath -> a -> InModule a
+ Cryptol.ModuleSystem.Binds: Mod :: [ImportG (ImpName PName)] -> ModKind -> Map Name (ImpName PName, ModuleInstanceArgs PName) -> Map Name (Mod a) -> NamingEnv -> !Set Name -> a -> Mod a
+ Cryptol.ModuleSystem.Binds: TopInst :: ModName -> ImpName PName -> ModuleInstanceArgs PName -> TopDef
+ Cryptol.ModuleSystem.Binds: TopMod :: ModName -> Mod () -> TopDef
+ Cryptol.ModuleSystem.Binds: [modDefines] :: Mod a -> NamingEnv
+ Cryptol.ModuleSystem.Binds: [modImports] :: Mod a -> [ImportG (ImpName PName)]
+ Cryptol.ModuleSystem.Binds: [modInstances] :: Mod a -> Map Name (ImpName PName, ModuleInstanceArgs PName)
+ Cryptol.ModuleSystem.Binds: [modKind] :: Mod a -> ModKind
+ Cryptol.ModuleSystem.Binds: [modMods] :: Mod a -> Map Name (Mod a)
+ Cryptol.ModuleSystem.Binds: [modPublic] :: Mod a -> !Set Name
+ Cryptol.ModuleSystem.Binds: [modState] :: Mod a -> a
+ Cryptol.ModuleSystem.Binds: class BindsNames a
+ Cryptol.ModuleSystem.Binds: data InModule a
+ Cryptol.ModuleSystem.Binds: data Mod a
+ Cryptol.ModuleSystem.Binds: data ModKind
+ Cryptol.ModuleSystem.Binds: data TopDef
+ Cryptol.ModuleSystem.Binds: defsOf :: BindsNames a => a -> Supply -> (NamingEnv, Supply)
+ Cryptol.ModuleSystem.Binds: ifaceSigToMod :: ModParamNames -> Mod ()
+ Cryptol.ModuleSystem.Binds: ifaceToMod :: IfaceG name -> Mod ()
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.Bind Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.Decl Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.NestedModule Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.Newtype Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.ParameterFun Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.ParameterType Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.PrimType Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.SigDecl Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.ModuleSystem.Binds.InModule (Cryptol.Parser.AST.TopDecl Cryptol.Parser.Name.PName))
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.Parser.AST.Schema Cryptol.Parser.Name.PName)
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames (Cryptol.Parser.AST.TParam Cryptol.Parser.Name.PName)
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames Cryptol.ModuleSystem.NamingEnv.NamingEnv
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames a => Cryptol.ModuleSystem.Binds.BindsNames (GHC.Maybe.Maybe a)
+ Cryptol.ModuleSystem.Binds: instance Cryptol.ModuleSystem.Binds.BindsNames a => Cryptol.ModuleSystem.Binds.BindsNames [a]
+ Cryptol.ModuleSystem.Binds: instance Data.Foldable.Foldable Cryptol.ModuleSystem.Binds.InModule
+ Cryptol.ModuleSystem.Binds: instance Data.Traversable.Traversable Cryptol.ModuleSystem.Binds.InModule
+ Cryptol.ModuleSystem.Binds: instance GHC.Base.Functor Cryptol.ModuleSystem.Binds.InModule
+ Cryptol.ModuleSystem.Binds: instance GHC.Base.Functor Cryptol.ModuleSystem.Binds.Mod
+ Cryptol.ModuleSystem.Binds: instance GHC.Base.Monoid Cryptol.ModuleSystem.Binds.BuildNamingEnv
+ Cryptol.ModuleSystem.Binds: instance GHC.Base.Semigroup Cryptol.ModuleSystem.Binds.BuildNamingEnv
+ Cryptol.ModuleSystem.Binds: instance GHC.Show.Show a => GHC.Show.Show (Cryptol.ModuleSystem.Binds.InModule a)
+ Cryptol.ModuleSystem.Binds: modBuilder :: ModBuilder a -> Supply -> ((a, [RenamerError]), Supply)
+ Cryptol.ModuleSystem.Binds: modNested :: Mod a -> Set Name
+ Cryptol.ModuleSystem.Binds: modToMap :: ImpName Name -> Mod () -> Map (ImpName Name) (Mod ()) -> Map (ImpName Name) (Mod ())
+ Cryptol.ModuleSystem.Binds: newModParam :: FreshM m => ModPath -> Ident -> Range -> Name -> m Name
+ Cryptol.ModuleSystem.Binds: topDeclsDefs :: ModPath -> [TopDecl PName] -> ModBuilder (Mod ())
+ Cryptol.ModuleSystem.Binds: topModuleDefs :: Module PName -> ModBuilder TopDef
+ Cryptol.ModuleSystem.Env: ALoadedFunctor :: LoadedModule -> LoadedEntity
+ Cryptol.ModuleSystem.Env: ALoadedInterface :: LoadedSignature -> LoadedEntity
+ Cryptol.ModuleSystem.Env: ALoadedModule :: LoadedModule -> LoadedEntity
+ Cryptol.ModuleSystem.Env: FileInfo :: Fingerprint -> Set FilePath -> Set ModName -> Set FilePath -> FileInfo
+ Cryptol.ModuleSystem.Env: FunctorParams :: FunctorParams -> ModContextParams
+ Cryptol.ModuleSystem.Env: InterfaceParams :: ModParamNames -> ModContextParams
+ Cryptol.ModuleSystem.Env: LoadedModuleData :: Iface -> Module -> Maybe ForeignSrc -> LoadedModuleData
+ Cryptol.ModuleSystem.Env: NoParams :: ModContextParams
+ Cryptol.ModuleSystem.Env: [fiFingerprint] :: FileInfo -> Fingerprint
+ Cryptol.ModuleSystem.Env: [fiForeignDeps] :: FileInfo -> Set FilePath
+ Cryptol.ModuleSystem.Env: [fiImportDeps] :: FileInfo -> Set ModName
+ Cryptol.ModuleSystem.Env: [fiIncludeDeps] :: FileInfo -> Set FilePath
+ Cryptol.ModuleSystem.Env: [lmData] :: LoadedModuleG a -> a
+ Cryptol.ModuleSystem.Env: [lmFileInfo] :: LoadedModuleG a -> !FileInfo
+ Cryptol.ModuleSystem.Env: [lmForeignSrc] :: LoadedModuleData -> Maybe ForeignSrc
+ Cryptol.ModuleSystem.Env: [lmLoadedSignatures] :: LoadedModules -> ![LoadedSignature]
+ Cryptol.ModuleSystem.Env: [lmdInterface] :: LoadedModuleData -> Iface
+ Cryptol.ModuleSystem.Env: [lmdModule] :: LoadedModuleData -> Module
+ Cryptol.ModuleSystem.Env: addLoadedSignature :: ModulePath -> String -> FileInfo -> NamingEnv -> ModName -> ModParamNames -> LoadedModules -> LoadedModules
+ Cryptol.ModuleSystem.Env: data FileInfo
+ Cryptol.ModuleSystem.Env: data LoadedEntity
+ Cryptol.ModuleSystem.Env: data LoadedModuleData
+ Cryptol.ModuleSystem.Env: data LoadedModuleG a
+ Cryptol.ModuleSystem.Env: data ModContextParams
+ Cryptol.ModuleSystem.Env: fileInfo :: Fingerprint -> Set FilePath -> Set ModName -> Maybe ForeignSrc -> FileInfo
+ Cryptol.ModuleSystem.Env: getLoadedEntities :: LoadedModules -> Map ModName LoadedEntity
+ Cryptol.ModuleSystem.Env: getLoadedNames :: LoadedModules -> Set ModName
+ Cryptol.ModuleSystem.Env: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Env.FileInfo
+ Cryptol.ModuleSystem.Env: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Env.LoadedModuleData
+ Cryptol.ModuleSystem.Env: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Cryptol.ModuleSystem.Env.LoadedModuleG a)
+ Cryptol.ModuleSystem.Env: instance GHC.Classes.Ord Cryptol.ModuleSystem.Env.ModulePath
+ Cryptol.ModuleSystem.Env: instance GHC.Generics.Generic (Cryptol.ModuleSystem.Env.LoadedModuleG a)
+ Cryptol.ModuleSystem.Env: instance GHC.Generics.Generic Cryptol.ModuleSystem.Env.FileInfo
+ Cryptol.ModuleSystem.Env: instance GHC.Generics.Generic Cryptol.ModuleSystem.Env.LoadedModuleData
+ Cryptol.ModuleSystem.Env: instance GHC.Show.Show Cryptol.ModuleSystem.Env.FileInfo
+ Cryptol.ModuleSystem.Env: instance GHC.Show.Show Cryptol.ModuleSystem.Env.LoadedModuleData
+ Cryptol.ModuleSystem.Env: instance GHC.Show.Show a => GHC.Show.Show (Cryptol.ModuleSystem.Env.LoadedModuleG a)
+ Cryptol.ModuleSystem.Env: isLoadedInterface :: ModName -> LoadedModules -> Bool
+ Cryptol.ModuleSystem.Env: lmInterface :: LoadedModule -> Iface
+ Cryptol.ModuleSystem.Env: lmModule :: LoadedModule -> Module
+ Cryptol.ModuleSystem.Env: lookupSignature :: ModName -> ModuleEnv -> Maybe LoadedSignature
+ Cryptol.ModuleSystem.Env: lookupTCEntity :: ModName -> ModuleEnv -> Maybe (LoadedModuleG TCTopEntity)
+ Cryptol.ModuleSystem.Env: modContextParamNames :: ModContextParams -> ModParamNames
+ Cryptol.ModuleSystem.Env: type LoadedModule = LoadedModuleG LoadedModuleData
+ Cryptol.ModuleSystem.Env: type LoadedSignature = LoadedModuleG ModParamNames
+ Cryptol.ModuleSystem.Exports: allExported :: Ord name => ExportSpec name -> Set name
+ Cryptol.ModuleSystem.Exports: exportedDecls :: Ord name => [TopDecl name] -> ExportSpec name
+ Cryptol.ModuleSystem.Fingerprint: fingerprintHexString :: Fingerprint -> String
+ Cryptol.ModuleSystem.Interface: IfaceNames :: name -> Set Name -> Set Name -> Set Name -> !Maybe Text -> IfaceNames name
+ Cryptol.ModuleSystem.Interface: [ifDeclIsPrim] :: IfaceDecl -> !Bool
+ Cryptol.ModuleSystem.Interface: [ifDefines] :: IfaceG name -> IfaceDecls
+ Cryptol.ModuleSystem.Interface: [ifFunctors] :: IfaceDecls -> !Map Name (IfaceG Name)
+ Cryptol.ModuleSystem.Interface: [ifNames] :: IfaceG name -> IfaceNames name
+ Cryptol.ModuleSystem.Interface: [ifSignatures] :: IfaceDecls -> !Map Name ModParamNames
+ Cryptol.ModuleSystem.Interface: [ifsDefines] :: IfaceNames name -> Set Name
+ Cryptol.ModuleSystem.Interface: [ifsDoc] :: IfaceNames name -> !Maybe Text
+ Cryptol.ModuleSystem.Interface: [ifsName] :: IfaceNames name -> name
+ Cryptol.ModuleSystem.Interface: [ifsNested] :: IfaceNames name -> Set Name
+ Cryptol.ModuleSystem.Interface: [ifsPublic] :: IfaceNames name -> Set Name
+ Cryptol.ModuleSystem.Interface: data IfaceNames name
+ Cryptol.ModuleSystem.Interface: ifModName :: IfaceG name -> name
+ Cryptol.ModuleSystem.Interface: ifaceForgetName :: IfaceG name -> IfaceG ()
+ Cryptol.ModuleSystem.Interface: ifaceOrigNameMap :: IfaceG name -> Map Namespace (Map OrigName Name)
+ Cryptol.ModuleSystem.Interface: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.ModuleSystem.Interface.IfaceG name)
+ Cryptol.ModuleSystem.Interface: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.ModuleSystem.Interface.IfaceNames name)
+ Cryptol.ModuleSystem.Interface: instance GHC.Generics.Generic (Cryptol.ModuleSystem.Interface.IfaceG name)
+ Cryptol.ModuleSystem.Interface: instance GHC.Generics.Generic (Cryptol.ModuleSystem.Interface.IfaceNames name)
+ Cryptol.ModuleSystem.Interface: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.ModuleSystem.Interface.IfaceG name)
+ Cryptol.ModuleSystem.Interface: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.ModuleSystem.Interface.IfaceNames name)
+ Cryptol.ModuleSystem.Monad: ExpandPropGuardsError :: ImportSource -> Error -> ModuleError
+ Cryptol.ModuleSystem.Monad: FFILoadErrors :: ModName -> [FFILoadError] -> ModuleError
+ Cryptol.ModuleSystem.Monad: FromSigImport :: Located ModName -> ImportSource
+ Cryptol.ModuleSystem.Monad: expandPropGuardsError :: Error -> ModuleM a
+ Cryptol.ModuleSystem.Monad: ffiLoadErrors :: ModName -> [FFILoadError] -> ModuleM a
+ Cryptol.ModuleSystem.Monad: getAllLoaded :: ModuleM (ModName -> Maybe (ModuleG (), IfaceG ()))
+ Cryptol.ModuleSystem.Monad: getAllLoadedSignatures :: ModuleM (ModName -> Maybe ModParamNames)
+ Cryptol.ModuleSystem.Monad: modifyEvalEnvM :: Traversable t => (EvalEnv -> Eval (t EvalEnv)) -> ModuleM (t ())
+ Cryptol.ModuleSystem.Name: GlobalName :: NameSource -> OrigName -> NameInfo
+ Cryptol.ModuleSystem.Name: LocalName :: Namespace -> Ident -> NameInfo
+ Cryptol.ModuleSystem.Name: asLocal :: Namespace -> Name -> Name
+ Cryptol.ModuleSystem.Name: freshNameFor :: ModPath -> Name -> Supply -> (Name, Supply)
+ Cryptol.ModuleSystem.Name: mapNameIdent :: (Ident -> Ident) -> Name -> Name
+ Cryptol.ModuleSystem.Name: mkLocal :: Namespace -> Ident -> Range -> Supply -> (Name, Supply)
+ Cryptol.ModuleSystem.Name: mkModParam :: ModPath -> Ident -> Range -> Name -> Supply -> (Name, Supply)
+ Cryptol.ModuleSystem.Name: nameModPath :: Name -> ModPath
+ Cryptol.ModuleSystem.Name: nameModPathMaybe :: Name -> Maybe ModPath
+ Cryptol.ModuleSystem.Name: nameTopModule :: Name -> ModName
+ Cryptol.ModuleSystem.Name: nameTopModuleMaybe :: Name -> Maybe ModName
+ Cryptol.ModuleSystem.Name: runSupply :: Supply -> (forall m. FreshM m => m a) -> (a, Supply)
+ Cryptol.ModuleSystem.Names: Ambig :: Set Name -> Names
+ Cryptol.ModuleSystem.Names: One :: Name -> Names
+ Cryptol.ModuleSystem.Names: anyOne :: Names -> Name
+ Cryptol.ModuleSystem.Names: data Names
+ Cryptol.ModuleSystem.Names: diffNames :: Names -> Names -> Maybe Names
+ Cryptol.ModuleSystem.Names: filterNames :: (Name -> Bool) -> Names -> Maybe Names
+ Cryptol.ModuleSystem.Names: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Names.Names
+ Cryptol.ModuleSystem.Names: instance GHC.Base.Semigroup Cryptol.ModuleSystem.Names.Names
+ Cryptol.ModuleSystem.Names: instance GHC.Generics.Generic Cryptol.ModuleSystem.Names.Names
+ Cryptol.ModuleSystem.Names: instance GHC.Show.Show Cryptol.ModuleSystem.Names.Names
+ Cryptol.ModuleSystem.Names: mapNames :: (Name -> Name) -> Names -> Names
+ Cryptol.ModuleSystem.Names: namesFromSet :: Set Name -> Names
+ Cryptol.ModuleSystem.Names: namesToList :: Names -> [Name]
+ Cryptol.ModuleSystem.Names: travNames :: Applicative f => (Name -> f Name) -> Names -> f Names
+ Cryptol.ModuleSystem.Names: unionManyNames :: [Names] -> Maybe Names
+ Cryptol.ModuleSystem.NamingEnv: filterPNames :: (PName -> Bool) -> NamingEnv -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: filterUNames :: (Name -> Bool) -> NamingEnv -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: findAmbig :: NamingEnv -> [[Name]]
+ Cryptol.ModuleSystem.NamingEnv: findShadowing :: NamingEnv -> NamingEnv -> [(PName, Name, [Name])]
+ Cryptol.ModuleSystem.NamingEnv: forceUnambig :: NamingEnv -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: isEmptyNamingEnv :: NamingEnv -> Bool
+ Cryptol.ModuleSystem.NamingEnv: lookupListNS :: Namespace -> PName -> NamingEnv -> [Name]
+ Cryptol.ModuleSystem.NamingEnv: mapNamingEnv :: (Name -> Name) -> NamingEnv -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: namingEnvFromNames :: Set Name -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: without :: NamingEnv -> NamingEnv -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: zipByTextName :: NamingEnv -> NamingEnv -> Map Name Name
+ Cryptol.ModuleSystem.Renamer: InvalidFunctorImport :: ImpName Name -> RenamerError
+ Cryptol.ModuleSystem.Renamer: ModuleKindMismatch :: Range -> ImpName Name -> ModKind -> ModKind -> RenamerError
+ Cryptol.ModuleSystem.Renamer: MultipleModParams :: Ident -> [Range] -> RenamerError
+ Cryptol.ModuleSystem.Renamer: PrefixAssocChanged :: PrefixOp -> Expr Name -> Located Name -> Fixity -> Expr Name -> RenamerWarning
+ Cryptol.ModuleSystem.Renamer: UnexpectedNest :: Range -> PName -> RenamerError
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.ModParam
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.ModuleInstanceArg
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.ModuleInstanceArgs
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.ModuleInstanceNamedArg
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.NestedModule
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.PropGuardCase
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.SigDecl
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.TopDecl
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.Utils.PP.PP Cryptol.ModuleSystem.Renamer.RenamedModule
+ Cryptol.ModuleSystem.Renamer.Error: AFunctor :: ModKind
+ Cryptol.ModuleSystem.Renamer.Error: AModule :: ModKind
+ Cryptol.ModuleSystem.Renamer.Error: ASignature :: ModKind
+ Cryptol.ModuleSystem.Renamer.Error: InvalidFunctorImport :: ImpName Name -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: ModParamName :: Range -> Ident -> DepName
+ Cryptol.ModuleSystem.Renamer.Error: ModPath :: ModPath -> DepName
+ Cryptol.ModuleSystem.Renamer.Error: ModuleKindMismatch :: Range -> ImpName Name -> ModKind -> ModKind -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: MultipleModParams :: Ident -> [Range] -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: PrefixAssocChanged :: PrefixOp -> Expr Name -> Located Name -> Fixity -> Expr Name -> RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: UnexpectedNest :: Range -> PName -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: data ModKind
+ Cryptol.ModuleSystem.Renamer.Error: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Renamer.Error.ModKind
+ Cryptol.ModuleSystem.Renamer.Error: instance Cryptol.Utils.PP.PP Cryptol.ModuleSystem.Renamer.Error.ModKind
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Classes.Eq Cryptol.ModuleSystem.Renamer.Error.ModKind
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Classes.Eq Cryptol.ModuleSystem.Renamer.Error.RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Classes.Ord Cryptol.ModuleSystem.Renamer.Error.ModKind
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Classes.Ord Cryptol.ModuleSystem.Renamer.Error.RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Generics.Generic Cryptol.ModuleSystem.Renamer.Error.ModKind
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Show.Show Cryptol.ModuleSystem.Renamer.Error.ModKind
+ Cryptol.ModuleSystem.Renamer.ImplicitImports: addImplicitNestedImports :: [TopDecl PName] -> [TopDecl PName]
+ Cryptol.ModuleSystem.Renamer.Imports: AFunctor :: ModKind
+ Cryptol.ModuleSystem.Renamer.Imports: AModule :: ModKind
+ Cryptol.ModuleSystem.Renamer.Imports: ASignature :: ModKind
+ Cryptol.ModuleSystem.Renamer.Imports: ResolvedModule :: NamingEnv -> !Set Name -> ModKind -> Set Name -> imps -> ResolvedModule imps
+ Cryptol.ModuleSystem.Renamer.Imports: [rmodDefines] :: ResolvedModule imps -> NamingEnv
+ Cryptol.ModuleSystem.Renamer.Imports: [rmodImports] :: ResolvedModule imps -> imps
+ Cryptol.ModuleSystem.Renamer.Imports: [rmodKind] :: ResolvedModule imps -> ModKind
+ Cryptol.ModuleSystem.Renamer.Imports: [rmodNested] :: ResolvedModule imps -> Set Name
+ Cryptol.ModuleSystem.Renamer.Imports: [rmodPublic] :: ResolvedModule imps -> !Set Name
+ Cryptol.ModuleSystem.Renamer.Imports: data ModKind
+ Cryptol.ModuleSystem.Renamer.Imports: data ResolvedModule imps
+ Cryptol.ModuleSystem.Renamer.Imports: instance Cryptol.ModuleSystem.Renamer.Imports.HasCurScope ()
+ Cryptol.ModuleSystem.Renamer.Imports: instance Cryptol.ModuleSystem.Renamer.Imports.HasCurScope Cryptol.ModuleSystem.Renamer.Imports.Todo
+ Cryptol.ModuleSystem.Renamer.Imports: resolveImports :: (ImpName Name -> Mod ()) -> TopDef -> Supply -> (Map (ImpName Name) ResolvedLocal, Supply)
+ Cryptol.ModuleSystem.Renamer.Imports: type ResolvedExt = ResolvedModule ()
+ Cryptol.ModuleSystem.Renamer.Imports: type ResolvedLocal = ResolvedModule NamingEnv
+ Cryptol.ModuleSystem.Renamer.Monad: RenModParam :: Ident -> Range -> ImpName Name -> Map Name Name -> RenModParam
+ Cryptol.ModuleSystem.Renamer.Monad: [renModParamInstance] :: RenModParam -> Map Name Name
+ Cryptol.ModuleSystem.Renamer.Monad: [renModParamName] :: RenModParam -> Ident
+ Cryptol.ModuleSystem.Renamer.Monad: [renModParamRange] :: RenModParam -> Range
+ Cryptol.ModuleSystem.Renamer.Monad: [renModParamSig] :: RenModParam -> ImpName Name
+ Cryptol.ModuleSystem.Renamer.Monad: [roExternal] :: RO -> Map ModName (Maybe Iface, Map (ImpName Name) (Mod ()))
+ Cryptol.ModuleSystem.Renamer.Monad: [roFromModParam] :: RO -> Map Name DepName
+ Cryptol.ModuleSystem.Renamer.Monad: [roModParams] :: RO -> Map Ident RenModParam
+ Cryptol.ModuleSystem.Renamer.Monad: [roResolvedModules] :: RO -> Map (ImpName Name) ResolvedLocal
+ Cryptol.ModuleSystem.Renamer.Monad: checkIsModule :: Range -> ImpName Name -> ModKind -> RenameM ()
+ Cryptol.ModuleSystem.Renamer.Monad: checkOverlap :: NamingEnv -> RenameM NamingEnv
+ Cryptol.ModuleSystem.Renamer.Monad: checkShadowing :: NamingEnv -> NamingEnv -> RenameM ()
+ Cryptol.ModuleSystem.Renamer.Monad: data RenModParam
+ Cryptol.ModuleSystem.Renamer.Monad: foldLoop :: [a] -> b -> (a -> b -> b) -> b
+ Cryptol.ModuleSystem.Renamer.Monad: getExternal :: RenameM (ImpName Name -> Mod ())
+ Cryptol.ModuleSystem.Renamer.Monad: getExternalMod :: ImpName Name -> RenameM (Mod ())
+ Cryptol.ModuleSystem.Renamer.Monad: getLocalModParamDeps :: RenameM (Map Ident DepName)
+ Cryptol.ModuleSystem.Renamer.Monad: getModParam :: Ident -> RenameM RenModParam
+ Cryptol.ModuleSystem.Renamer.Monad: getNamesFromModParams :: RenameM (Map Name DepName)
+ Cryptol.ModuleSystem.Renamer.Monad: getTopModuleIface :: ImpName Name -> RenameM (Maybe Iface)
+ Cryptol.ModuleSystem.Renamer.Monad: lookupDefines :: ImpName Name -> RenameM NamingEnv
+ Cryptol.ModuleSystem.Renamer.Monad: lookupDefinesAndSubs :: ImpName Name -> RenameM (NamingEnv, Set Name)
+ Cryptol.ModuleSystem.Renamer.Monad: lookupModuleThing :: ImpName Name -> RenameM (Either ResolvedLocal (Mod ()))
+ Cryptol.ModuleSystem.Renamer.Monad: lookupResolved :: ImpName Name -> RenameM ResolvedLocal
+ Cryptol.ModuleSystem.Renamer.Monad: recordError :: RenamerError -> RenameM ()
+ Cryptol.ModuleSystem.Renamer.Monad: recordImport :: Range -> ImpName Name -> RenameM ()
+ Cryptol.ModuleSystem.Renamer.Monad: recordWarning :: RenamerWarning -> RenameM ()
+ Cryptol.ModuleSystem.Renamer.Monad: setModParams :: [RenModParam] -> RenameM a -> RenameM a
+ Cryptol.ModuleSystem.Renamer.Monad: setResolvedLocals :: Map (ImpName Name) ResolvedLocal -> RenameM a -> RenameM a
+ Cryptol.Parser: RST :: PreProc
+ Cryptol.Parser.AST: AddParams :: ModuleInstanceArg name
+ Cryptol.Parser.AST: DForeign :: BindDef name
+ Cryptol.Parser.AST: DInterfaceConstraint :: Maybe Text -> Located [Prop name] -> TopDecl name
+ Cryptol.Parser.AST: DModParam :: ModParam name -> TopDecl name
+ Cryptol.Parser.AST: DParamDecl :: Range -> Signature name -> TopDecl name
+ Cryptol.Parser.AST: DParameterDecl :: SigDecl name -> ParamDecl name
+ Cryptol.Parser.AST: DPropGuards :: [PropGuardCase name] -> BindDef name
+ Cryptol.Parser.AST: DefaultInstAnonArg :: [TopDecl name] -> ModuleInstanceArgs name
+ Cryptol.Parser.AST: DefaultInstArg :: Located (ModuleInstanceArg name) -> ModuleInstanceArgs name
+ Cryptol.Parser.AST: EPrefix :: PrefixOp -> Expr n -> Expr n
+ Cryptol.Parser.AST: ExpandPropGuards :: String -> Pass
+ Cryptol.Parser.AST: FunctorInstance :: Located (ImpName name) -> ModuleInstanceArgs name -> ModuleInstance name -> ModuleDefinition name
+ Cryptol.Parser.AST: InterfaceModule :: Signature name -> ModuleDefinition name
+ Cryptol.Parser.AST: ModParam :: Located (ImpName name) -> Maybe ModName -> !Ident -> Maybe (Located Text) -> !Map name name -> ModParam name
+ Cryptol.Parser.AST: ModuleArg :: ImpName name -> ModuleInstanceArg name
+ Cryptol.Parser.AST: ModuleInstanceNamedArg :: Located Ident -> Located (ModuleInstanceArg name) -> ModuleInstanceNamedArg name
+ Cryptol.Parser.AST: NamedInstArgs :: [ModuleInstanceNamedArg name] -> ModuleInstanceArgs name
+ Cryptol.Parser.AST: NormalModule :: [TopDecl name] -> ModuleDefinition name
+ Cryptol.Parser.AST: ParameterArg :: Ident -> ModuleInstanceArg name
+ Cryptol.Parser.AST: PrefixComplement :: PrefixOp
+ Cryptol.Parser.AST: PrefixNeg :: PrefixOp
+ Cryptol.Parser.AST: PropGuardCase :: [Located (Prop name)] -> Expr name -> PropGuardCase name
+ Cryptol.Parser.AST: SigPropSyn :: PropSyn name -> Maybe Text -> SigDecl name
+ Cryptol.Parser.AST: SigTySyn :: TySyn name -> Maybe Text -> SigDecl name
+ Cryptol.Parser.AST: Signature :: ![Located (ImportG (ImpName name))] -> [ParameterType name] -> [Located (Prop name)] -> [SigDecl name] -> [ParameterFun name] -> Signature name
+ Cryptol.Parser.AST: [iInst] :: ImportG mname -> !Maybe (ModuleInstanceArgs PName)
+ Cryptol.Parser.AST: [mDef] :: ModuleG mname name -> ModuleDefinition name
+ Cryptol.Parser.AST: [mpAs] :: ModParam name -> Maybe ModName
+ Cryptol.Parser.AST: [mpDoc] :: ModParam name -> Maybe (Located Text)
+ Cryptol.Parser.AST: [mpName] :: ModParam name -> !Ident
+ Cryptol.Parser.AST: [mpRenaming] :: ModParam name -> !Map name name
+ Cryptol.Parser.AST: [mpSignature] :: ModParam name -> Located (ImpName name)
+ Cryptol.Parser.AST: [nConName] :: Newtype name -> !name
+ Cryptol.Parser.AST: [pgcExpr] :: PropGuardCase name -> Expr name
+ Cryptol.Parser.AST: [pgcProps] :: PropGuardCase name -> [Located (Prop name)]
+ Cryptol.Parser.AST: [sigConstraints] :: Signature name -> [Located (Prop name)]
+ Cryptol.Parser.AST: [sigDecls] :: Signature name -> [SigDecl name]
+ Cryptol.Parser.AST: [sigFunParams] :: Signature name -> [ParameterFun name]
+ Cryptol.Parser.AST: [sigImports] :: Signature name -> ![Located (ImportG (ImpName name))]
+ Cryptol.Parser.AST: [sigTypeParams] :: Signature name -> [ParameterType name]
+ Cryptol.Parser.AST: asEApps :: Expr n -> (Expr n, [Expr n])
+ Cryptol.Parser.AST: data ModParam name
+ Cryptol.Parser.AST: data ModuleDefinition name
+ Cryptol.Parser.AST: data ModuleInstanceArg name
+ Cryptol.Parser.AST: data ModuleInstanceArgs name
+ Cryptol.Parser.AST: data ModuleInstanceNamedArg name
+ Cryptol.Parser.AST: data ParamDecl name
+ Cryptol.Parser.AST: data PrefixOp
+ Cryptol.Parser.AST: data PropGuardCase name
+ Cryptol.Parser.AST: data SigDecl name
+ Cryptol.Parser.AST: data Signature name
+ Cryptol.Parser.AST: emptyModuleInstance :: Ord name => ModuleInstance name
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ModParam name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ModuleDefinition name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ModuleInstanceArg name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ModuleInstanceArgs name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ModuleInstanceNamedArg name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ParamDecl name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.SigDecl name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData Cryptol.Parser.AST.PrefixOp
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.ModParam name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.ModuleDefinition name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.ModuleInstanceArg name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.ModuleInstanceArgs name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.ModuleInstanceNamedArg name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.ParamDecl name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.PropGuardCase name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.SigDecl name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.Signature name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.ModParam name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.ModuleDefinition name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.ModuleInstanceArgs name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.ModuleInstanceNamedArg name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.ParamDecl name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.SigDecl name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.Signature name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.Position.HasLoc (Cryptol.Parser.AST.ModParam name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.Position.HasLoc (Cryptol.Parser.AST.ParamDecl name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.Position.HasLoc (Cryptol.Parser.AST.PropSyn name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.Position.HasLoc (Cryptol.Parser.AST.SigDecl name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.Position.HasLoc (Cryptol.Parser.AST.TySyn name)
+ Cryptol.Parser.AST: instance Cryptol.Utils.PP.PPName name => Cryptol.Utils.PP.PP [Cryptol.Parser.AST.Prop name]
+ Cryptol.Parser.AST: instance GHC.Base.Functor Cryptol.Parser.AST.PropGuardCase
+ Cryptol.Parser.AST: instance GHC.Classes.Eq Cryptol.Parser.AST.PrefixOp
+ Cryptol.Parser.AST: instance GHC.Classes.Eq name => GHC.Classes.Eq (Cryptol.Parser.AST.ImpName name)
+ Cryptol.Parser.AST: instance GHC.Classes.Eq name => GHC.Classes.Eq (Cryptol.Parser.AST.ModParam name)
+ Cryptol.Parser.AST: instance GHC.Classes.Eq name => GHC.Classes.Eq (Cryptol.Parser.AST.PropGuardCase name)
+ Cryptol.Parser.AST: instance GHC.Classes.Ord name => GHC.Classes.Ord (Cryptol.Parser.AST.ImpName name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ModParam name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ModuleDefinition name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ModuleInstanceArg name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ModuleInstanceArgs name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ModuleInstanceNamedArg name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ParamDecl name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.PropGuardCase name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.SigDecl name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.Signature name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic Cryptol.Parser.AST.PrefixOp
+ Cryptol.Parser.AST: instance GHC.Show.Show Cryptol.Parser.AST.PrefixOp
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.ModParam name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.ModuleDefinition name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.ModuleInstanceArg name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.ModuleInstanceArgs name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.ModuleInstanceNamedArg name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.ParamDecl name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.PropGuardCase name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.SigDecl name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.Signature name)
+ Cryptol.Parser.AST: isParamDecl :: TopDecl a -> Bool
+ Cryptol.Parser.AST: mDecls :: ModuleG mname name -> [TopDecl name]
+ Cryptol.Parser.AST: mIsFunctor :: ModuleG mname nmae -> Bool
+ Cryptol.Parser.AST: mModParams :: ModuleG mname name -> [ModParam name]
+ Cryptol.Parser.AST: prefixFixity :: PrefixOp -> Fixity
+ Cryptol.Parser.AST: type ModuleInstance name = Map name name
+ Cryptol.Parser.ExpandPropGuards: NoSignature :: Located PName -> Error
+ Cryptol.Parser.ExpandPropGuards: data Error
+ Cryptol.Parser.ExpandPropGuards: expandBind :: Bind PName -> ExpandPropGuardsM [Bind PName]
+ Cryptol.Parser.ExpandPropGuards: expandDecl :: Decl PName -> ExpandPropGuardsM [Decl PName]
+ Cryptol.Parser.ExpandPropGuards: expandModuleDef :: ModuleDefinition PName -> ExpandPropGuardsM (ModuleDefinition PName)
+ Cryptol.Parser.ExpandPropGuards: expandPropGuards :: ModuleG mname PName -> ExpandPropGuardsM (ModuleG mname PName)
+ Cryptol.Parser.ExpandPropGuards: expandTopDecl :: TopDecl PName -> ExpandPropGuardsM [TopDecl PName]
+ Cryptol.Parser.ExpandPropGuards: instance Control.DeepSeq.NFData Cryptol.Parser.ExpandPropGuards.Error
+ Cryptol.Parser.ExpandPropGuards: instance Cryptol.Utils.PP.PP Cryptol.Parser.ExpandPropGuards.Error
+ Cryptol.Parser.ExpandPropGuards: instance GHC.Generics.Generic Cryptol.Parser.ExpandPropGuards.Error
+ Cryptol.Parser.ExpandPropGuards: instance GHC.Show.Show Cryptol.Parser.ExpandPropGuards.Error
+ Cryptol.Parser.ExpandPropGuards: newName :: Located PName -> [Prop PName] -> ExpandPropGuardsM (Located PName)
+ Cryptol.Parser.ExpandPropGuards: patternToExpr :: Pattern PName -> Expr PName
+ Cryptol.Parser.ExpandPropGuards: runExpandPropGuardsM :: ExpandPropGuardsM a -> Either Error a
+ Cryptol.Parser.ExpandPropGuards: type ExpandPropGuardsM a = Either Error a
+ Cryptol.Parser.Lexer: KW_foreign :: TokenKW
+ Cryptol.Parser.Lexer: KW_interface :: TokenKW
+ Cryptol.Parser.Name: ExpandPropGuards :: String -> Pass
+ Cryptol.Parser.Names: namesNT :: Newtype name -> ([Located name], ())
+ Cryptol.Parser.Position: rangeWithin :: Range -> Range -> Bool
+ Cryptol.Parser.Token: KW_foreign :: TokenKW
+ Cryptol.Parser.Token: KW_interface :: TokenKW
+ Cryptol.Parser.Unlit: RST :: PreProc
+ Cryptol.REPL.Help: helpForNamed :: PName -> REPL ()
+ Cryptol.REPL.Monad: InstantiationsNotFound :: Schema -> REPLException
+ Cryptol.REPL.Monad: getRandomGen :: REPL TFGen
+ Cryptol.REPL.Monad: setRandomGen :: TFGen -> REPL ()
+ Cryptol.REPL.Monad: withRandomGen :: (TFGen -> REPL (a, TFGen)) -> REPL a
+ Cryptol.Testing.Random: randomTests' :: (MonadIO m, RandomGen g) => (Integer -> m ()) -> Integer -> Value -> [Gen g Concrete] -> g -> m ((TestResult, Integer), g)
+ Cryptol.Testing.Random: returnTests' :: RandomGen g => g -> [Gen g Concrete] -> Value -> Int -> IO ([([Value], Value)], g)
+ Cryptol.TypeCheck: DeclarationRequiresSignatureCtrGrd :: Ident -> Error
+ Cryptol.TypeCheck: FunctorInstanceBadArgument :: Ident -> Error
+ Cryptol.TypeCheck: FunctorInstanceBadBacktick :: BadBacktickInstance -> Error
+ Cryptol.TypeCheck: FunctorInstanceMissingArgument :: Ident -> Error
+ Cryptol.TypeCheck: FunctorInstanceMissingName :: Namespace -> Ident -> Error
+ Cryptol.TypeCheck: InvalidConstraintGuard :: Prop -> Error
+ Cryptol.TypeCheck: MissingModParam :: Ident -> Error
+ Cryptol.TypeCheck: NestedConstraintGuard :: Ident -> Error
+ Cryptol.TypeCheck: NonExhaustivePropGuards :: Name -> Warning
+ Cryptol.TypeCheck: SchemaMismatch :: Ident -> Schema -> Schema -> Error
+ Cryptol.TypeCheck: UnsupportedFFIKind :: TypeSource -> TParam -> Kind -> Error
+ Cryptol.TypeCheck: UnsupportedFFIType :: TypeSource -> FFITypeError -> Error
+ Cryptol.TypeCheck: [inpParams] :: InferInput -> !ModParamNames
+ Cryptol.TypeCheck: [inpSignatures] :: InferInput -> !Map Name ModParamNames
+ Cryptol.TypeCheck: [inpTopModules] :: InferInput -> ModName -> Maybe (ModuleG (), IfaceG ())
+ Cryptol.TypeCheck: [inpTopSignatures] :: InferInput -> ModName -> Maybe ModParamNames
+ Cryptol.TypeCheck.AST: DForeign :: FFIFunType -> DeclDef
+ Cryptol.TypeCheck.AST: EPropGuards :: [([Prop], Expr)] -> Type -> Expr
+ Cryptol.TypeCheck.AST: ImpNested :: name -> ImpName name
+ Cryptol.TypeCheck.AST: ImpTop :: ModName -> ImpName name
+ Cryptol.TypeCheck.AST: TCTopModule :: ModuleG ModName -> TCTopEntity
+ Cryptol.TypeCheck.AST: TCTopSignature :: ModName -> ModParamNames -> TCTopEntity
+ Cryptol.TypeCheck.AST: [iInst] :: ImportG mname -> !Maybe (ModuleInstanceArgs PName)
+ Cryptol.TypeCheck.AST: [mDoc] :: ModuleG mname -> !Maybe Text
+ Cryptol.TypeCheck.AST: [mNested] :: ModuleG mname -> !Set Name
+ Cryptol.TypeCheck.AST: [mParams] :: ModuleG mname -> FunctorParams
+ Cryptol.TypeCheck.AST: [mSignatures] :: ModuleG mname -> !Map Name ModParamNames
+ Cryptol.TypeCheck.AST: [mSubmodules] :: ModuleG mname -> Map Name (IfaceNames Name)
+ Cryptol.TypeCheck.AST: data ImpName name
+ Cryptol.TypeCheck.AST: data TCTopEntity
+ Cryptol.TypeCheck.AST: dropLocs :: Expr -> Expr
+ Cryptol.TypeCheck.AST: findForeignDecls :: ModuleG mname -> [(Name, FFIFunType)]
+ Cryptol.TypeCheck.AST: findForeignDeclsInFunctors :: ModuleG mname -> [Name]
+ Cryptol.TypeCheck.AST: instance Control.DeepSeq.NFData Cryptol.TypeCheck.AST.TCTopEntity
+ Cryptol.TypeCheck.AST: instance Cryptol.Utils.PP.PP (Cryptol.TypeCheck.PP.WithNames Cryptol.TypeCheck.AST.TCTopEntity)
+ Cryptol.TypeCheck.AST: instance Cryptol.Utils.PP.PP Cryptol.TypeCheck.AST.TCTopEntity
+ Cryptol.TypeCheck.AST: instance GHC.Generics.Generic Cryptol.TypeCheck.AST.TCTopEntity
+ Cryptol.TypeCheck.AST: instance GHC.Show.Show Cryptol.TypeCheck.AST.TCTopEntity
+ Cryptol.TypeCheck.AST: splitApp :: Expr -> Maybe (Expr, Expr)
+ Cryptol.TypeCheck.AST: splitLoc :: Expr -> Maybe (Range, Expr)
+ Cryptol.TypeCheck.AST: tcTopEntityToModule :: TCTopEntity -> Module
+ Cryptol.TypeCheck.AST: tcTopEntitytName :: TCTopEntity -> ModName
+ Cryptol.TypeCheck.Error: BIAbstractType :: BIWhat
+ Cryptol.TypeCheck.Error: BIForeign :: BIWhat
+ Cryptol.TypeCheck.Error: BIFunctor :: BIWhat
+ Cryptol.TypeCheck.Error: BIInterface :: BIWhat
+ Cryptol.TypeCheck.Error: BIMultipleParams :: Ident -> BadBacktickInstance
+ Cryptol.TypeCheck.Error: BINested :: [(BIWhat, Name)] -> BadBacktickInstance
+ Cryptol.TypeCheck.Error: BIPolymorphicArgument :: Ident -> Ident -> BadBacktickInstance
+ Cryptol.TypeCheck.Error: BIPrimitive :: BIWhat
+ Cryptol.TypeCheck.Error: DeclarationRequiresSignatureCtrGrd :: Ident -> Error
+ Cryptol.TypeCheck.Error: FunctorInstanceBadArgument :: Ident -> Error
+ Cryptol.TypeCheck.Error: FunctorInstanceBadBacktick :: BadBacktickInstance -> Error
+ Cryptol.TypeCheck.Error: FunctorInstanceMissingArgument :: Ident -> Error
+ Cryptol.TypeCheck.Error: FunctorInstanceMissingName :: Namespace -> Ident -> Error
+ Cryptol.TypeCheck.Error: InvalidConstraintGuard :: Prop -> Error
+ Cryptol.TypeCheck.Error: MissingModParam :: Ident -> Error
+ Cryptol.TypeCheck.Error: NestedConstraintGuard :: Ident -> Error
+ Cryptol.TypeCheck.Error: NonExhaustivePropGuards :: Name -> Warning
+ Cryptol.TypeCheck.Error: SchemaMismatch :: Ident -> Schema -> Schema -> Error
+ Cryptol.TypeCheck.Error: UnsupportedFFIKind :: TypeSource -> TParam -> Kind -> Error
+ Cryptol.TypeCheck.Error: UnsupportedFFIType :: TypeSource -> FFITypeError -> Error
+ Cryptol.TypeCheck.Error: data BIWhat
+ Cryptol.TypeCheck.Error: data BadBacktickInstance
+ Cryptol.TypeCheck.Error: instance Control.DeepSeq.NFData Cryptol.TypeCheck.Error.BIWhat
+ Cryptol.TypeCheck.Error: instance Control.DeepSeq.NFData Cryptol.TypeCheck.Error.BadBacktickInstance
+ Cryptol.TypeCheck.Error: instance GHC.Generics.Generic Cryptol.TypeCheck.Error.BIWhat
+ Cryptol.TypeCheck.Error: instance GHC.Generics.Generic Cryptol.TypeCheck.Error.BadBacktickInstance
+ Cryptol.TypeCheck.Error: instance GHC.Show.Show Cryptol.TypeCheck.Error.BIWhat
+ Cryptol.TypeCheck.Error: instance GHC.Show.Show Cryptol.TypeCheck.Error.BadBacktickInstance
+ Cryptol.TypeCheck.FFI: toFFIFunType :: Schema -> Either FFITypeError ([Prop], FFIFunType)
+ Cryptol.TypeCheck.FFI.Error: FFIBadArrayType :: FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: FFIBadComponentTypes :: [FFITypeError] -> FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: FFIBadFloatSize :: FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: FFIBadType :: FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: FFIBadWordSize :: FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: FFINotFunction :: FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: FFITypeError :: Type -> FFITypeErrorReason -> FFITypeError
+ Cryptol.TypeCheck.FFI.Error: data FFITypeError
+ Cryptol.TypeCheck.FFI.Error: data FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.Error.FFITypeError
+ Cryptol.TypeCheck.FFI.Error: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.Error.FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: instance Cryptol.TypeCheck.Subst.TVars Cryptol.TypeCheck.FFI.Error.FFITypeError
+ Cryptol.TypeCheck.FFI.Error: instance Cryptol.TypeCheck.Subst.TVars Cryptol.TypeCheck.FFI.Error.FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: instance Cryptol.TypeCheck.Type.FVS Cryptol.TypeCheck.FFI.Error.FFITypeError
+ Cryptol.TypeCheck.FFI.Error: instance Cryptol.TypeCheck.Type.FVS Cryptol.TypeCheck.FFI.Error.FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: instance Cryptol.Utils.PP.PP (Cryptol.TypeCheck.PP.WithNames Cryptol.TypeCheck.FFI.Error.FFITypeError)
+ Cryptol.TypeCheck.FFI.Error: instance Cryptol.Utils.PP.PP (Cryptol.TypeCheck.PP.WithNames Cryptol.TypeCheck.FFI.Error.FFITypeErrorReason)
+ Cryptol.TypeCheck.FFI.Error: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.Error.FFITypeError
+ Cryptol.TypeCheck.FFI.Error: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.Error.FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.Error: instance GHC.Show.Show Cryptol.TypeCheck.FFI.Error.FFITypeError
+ Cryptol.TypeCheck.FFI.Error: instance GHC.Show.Show Cryptol.TypeCheck.FFI.Error.FFITypeErrorReason
+ Cryptol.TypeCheck.FFI.FFIType: FFIArray :: [Type] -> FFIBasicType -> FFIType
+ Cryptol.TypeCheck.FFI.FFIType: FFIBasic :: FFIBasicType -> FFIType
+ Cryptol.TypeCheck.FFI.FFIType: FFIBasicRef :: FFIBasicRefType -> FFIBasicType
+ Cryptol.TypeCheck.FFI.FFIType: FFIBasicVal :: FFIBasicValType -> FFIBasicType
+ Cryptol.TypeCheck.FFI.FFIType: FFIBool :: FFIType
+ Cryptol.TypeCheck.FFI.FFIType: FFIFloat :: Integer -> Integer -> FFIFloatSize -> FFIBasicValType
+ Cryptol.TypeCheck.FFI.FFIType: FFIFloat32 :: FFIFloatSize
+ Cryptol.TypeCheck.FFI.FFIType: FFIFloat64 :: FFIFloatSize
+ Cryptol.TypeCheck.FFI.FFIType: FFIFunType :: [TParam] -> [FFIType] -> FFIType -> FFIFunType
+ Cryptol.TypeCheck.FFI.FFIType: FFIInteger :: Maybe Type -> FFIBasicRefType
+ Cryptol.TypeCheck.FFI.FFIType: FFIRational :: FFIBasicRefType
+ Cryptol.TypeCheck.FFI.FFIType: FFIRecord :: RecordMap Ident FFIType -> FFIType
+ Cryptol.TypeCheck.FFI.FFIType: FFITuple :: [FFIType] -> FFIType
+ Cryptol.TypeCheck.FFI.FFIType: FFIWord :: Integer -> FFIWordSize -> FFIBasicValType
+ Cryptol.TypeCheck.FFI.FFIType: FFIWord16 :: FFIWordSize
+ Cryptol.TypeCheck.FFI.FFIType: FFIWord32 :: FFIWordSize
+ Cryptol.TypeCheck.FFI.FFIType: FFIWord64 :: FFIWordSize
+ Cryptol.TypeCheck.FFI.FFIType: FFIWord8 :: FFIWordSize
+ Cryptol.TypeCheck.FFI.FFIType: [ffiArgTypes] :: FFIFunType -> [FFIType]
+ Cryptol.TypeCheck.FFI.FFIType: [ffiRetType] :: FFIFunType -> FFIType
+ Cryptol.TypeCheck.FFI.FFIType: [ffiTParams] :: FFIFunType -> [TParam]
+ Cryptol.TypeCheck.FFI.FFIType: data FFIBasicRefType
+ Cryptol.TypeCheck.FFI.FFIType: data FFIBasicType
+ Cryptol.TypeCheck.FFI.FFIType: data FFIBasicValType
+ Cryptol.TypeCheck.FFI.FFIType: data FFIFloatSize
+ Cryptol.TypeCheck.FFI.FFIType: data FFIFunType
+ Cryptol.TypeCheck.FFI.FFIType: data FFIType
+ Cryptol.TypeCheck.FFI.FFIType: data FFIWordSize
+ Cryptol.TypeCheck.FFI.FFIType: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.FFIType.FFIBasicRefType
+ Cryptol.TypeCheck.FFI.FFIType: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.FFIType.FFIBasicType
+ Cryptol.TypeCheck.FFI.FFIType: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.FFIType.FFIBasicValType
+ Cryptol.TypeCheck.FFI.FFIType: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.FFIType.FFIFloatSize
+ Cryptol.TypeCheck.FFI.FFIType: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.FFIType.FFIFunType
+ Cryptol.TypeCheck.FFI.FFIType: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.FFIType.FFIType
+ Cryptol.TypeCheck.FFI.FFIType: instance Control.DeepSeq.NFData Cryptol.TypeCheck.FFI.FFIType.FFIWordSize
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.FFIType.FFIBasicRefType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.FFIType.FFIBasicType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.FFIType.FFIBasicValType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.FFIType.FFIFloatSize
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.FFIType.FFIFunType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.FFIType.FFIType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Generics.Generic Cryptol.TypeCheck.FFI.FFIType.FFIWordSize
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Show.Show Cryptol.TypeCheck.FFI.FFIType.FFIBasicRefType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Show.Show Cryptol.TypeCheck.FFI.FFIType.FFIBasicType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Show.Show Cryptol.TypeCheck.FFI.FFIType.FFIBasicValType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Show.Show Cryptol.TypeCheck.FFI.FFIType.FFIFloatSize
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Show.Show Cryptol.TypeCheck.FFI.FFIType.FFIFunType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Show.Show Cryptol.TypeCheck.FFI.FFIType.FFIType
+ Cryptol.TypeCheck.FFI.FFIType: instance GHC.Show.Show Cryptol.TypeCheck.FFI.FFIType.FFIWordSize
+ Cryptol.TypeCheck.Infer: inferTopModule :: Module Name -> InferM TCTopEntity
+ Cryptol.TypeCheck.InferTypes: CtFFI :: Name -> ConstraintSource
+ Cryptol.TypeCheck.InferTypes: CtPropGuardsExhaustive :: Name -> ConstraintSource
+ Cryptol.TypeCheck.Interface: genIfaceNames :: ModuleG name -> IfaceNames name
+ Cryptol.TypeCheck.Interface: genIfaceWithNames :: IfaceNames name -> ModuleG ignored -> IfaceG name
+ Cryptol.TypeCheck.Interface: genModDefines :: ModuleG name -> Set Name
+ Cryptol.TypeCheck.Kind: checkPropGuards :: [Located (Prop Name)] -> InferM [Prop]
+ Cryptol.TypeCheck.Module: doFunctorInst :: Located (ImpName Name) -> Located (ImpName Name) -> ModuleInstanceArgs Name -> Map Name Name -> Maybe Text -> InferM (Maybe TCTopEntity)
+ Cryptol.TypeCheck.ModuleBacktickInstance: doBacktickInstance :: Set (MBQual TParam) -> [Prop] -> Map (MBQual Name) Type -> ModuleG (Located (ImpName Name)) -> InferM (ModuleG (Located (ImpName Name)))
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.AddParams Cryptol.TypeCheck.AST.Decl
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.AddParams Cryptol.TypeCheck.AST.DeclGroup
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.AddParams Cryptol.TypeCheck.Type.Newtype
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.AddParams Cryptol.TypeCheck.Type.TySyn
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.AddParams a => Cryptol.TypeCheck.ModuleBacktickInstance.AddParams (Data.Map.Internal.Map Cryptol.ModuleSystem.Name.Name a)
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.AddParams a => Cryptol.TypeCheck.ModuleBacktickInstance.AddParams [a]
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewType Cryptol.TypeCheck.Type.Schema
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewType Cryptol.TypeCheck.Type.Type
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewType a => Cryptol.TypeCheck.ModuleBacktickInstance.RewType [a]
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewType b => Cryptol.TypeCheck.ModuleBacktickInstance.RewType (Cryptol.Utils.RecordMap.RecordMap a b)
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewVal Cryptol.TypeCheck.AST.Decl
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewVal Cryptol.TypeCheck.AST.DeclDef
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewVal Cryptol.TypeCheck.AST.DeclGroup
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewVal Cryptol.TypeCheck.AST.Expr
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewVal Cryptol.TypeCheck.AST.Match
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewVal a => Cryptol.TypeCheck.ModuleBacktickInstance.RewVal [a]
+ Cryptol.TypeCheck.ModuleBacktickInstance: instance Cryptol.TypeCheck.ModuleBacktickInstance.RewVal b => Cryptol.TypeCheck.ModuleBacktickInstance.RewVal (Cryptol.Utils.RecordMap.RecordMap a b)
+ Cryptol.TypeCheck.ModuleBacktickInstance: type MBQual a = (Maybe ModName, a)
+ Cryptol.TypeCheck.ModuleInstance: class ModuleInstance t
+ Cryptol.TypeCheck.ModuleInstance: doMap :: (Su, ModuleInstance a) => Map Name a -> Map Name a
+ Cryptol.TypeCheck.ModuleInstance: doSet :: Su => Set Name -> Set Name
+ Cryptol.TypeCheck.ModuleInstance: doTInst :: (Su, TVars a) => a -> a
+ Cryptol.TypeCheck.ModuleInstance: doTVInst :: (Su, TVars a, TraverseNames a) => a -> a
+ Cryptol.TypeCheck.ModuleInstance: doVInst :: (Su, TraverseNames a) => a -> a
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance (Cryptol.TypeCheck.AST.ModuleG name)
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.ModuleSystem.Name.Name
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.AST.Decl
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.AST.DeclGroup
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.AbstractType
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.ModParam
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.ModParamNames
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.ModTParam
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.ModVParam
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.Newtype
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.Schema
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.TySyn
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance Cryptol.TypeCheck.Type.Type
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance a => Cryptol.TypeCheck.ModuleInstance.ModuleInstance (Cryptol.Parser.Position.Located a)
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance a => Cryptol.TypeCheck.ModuleInstance.ModuleInstance [a]
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance name => Cryptol.TypeCheck.ModuleInstance.ModuleInstance (Cryptol.ModuleSystem.Interface.IfaceNames name)
+ Cryptol.TypeCheck.ModuleInstance: instance Cryptol.TypeCheck.ModuleInstance.ModuleInstance name => Cryptol.TypeCheck.ModuleInstance.ModuleInstance (Cryptol.Parser.AST.ImpName name)
+ Cryptol.TypeCheck.ModuleInstance: moduleInstance :: (ModuleInstance t, Su) => t -> t
+ Cryptol.TypeCheck.ModuleInstance: type Su = (?tSu :: Subst, ?vSu :: Map Name Name)
+ Cryptol.TypeCheck.Monad: SignatureScope :: Name -> Maybe Text -> ScopeName
+ Cryptol.TypeCheck.Monad: TopSignatureScope :: ModName -> ScopeName
+ Cryptol.TypeCheck.Monad: [iExtModules] :: RO -> ModName -> Maybe (ModuleG (), IfaceG ())
+ Cryptol.TypeCheck.Monad: [iExtSignatures] :: RO -> ModName -> Maybe ModParamNames
+ Cryptol.TypeCheck.Monad: [inpParams] :: InferInput -> !ModParamNames
+ Cryptol.TypeCheck.Monad: [inpSignatures] :: InferInput -> !Map Name ModParamNames
+ Cryptol.TypeCheck.Monad: [inpTopModules] :: InferInput -> ModName -> Maybe (ModuleG (), IfaceG ())
+ Cryptol.TypeCheck.Monad: [inpTopSignatures] :: InferInput -> ModName -> Maybe ModParamNames
+ Cryptol.TypeCheck.Monad: abortIfErrors :: InferM ()
+ Cryptol.TypeCheck.Monad: addFunctors :: Map Name (ModuleG Name) -> InferM ()
+ Cryptol.TypeCheck.Monad: addModParam :: ModParam -> InferM ()
+ Cryptol.TypeCheck.Monad: addSignatures :: Map Name ModParamNames -> InferM ()
+ Cryptol.TypeCheck.Monad: addSubmodules :: Map Name (IfaceNames Name) -> InferM ()
+ Cryptol.TypeCheck.Monad: endSignature :: InferM ()
+ Cryptol.TypeCheck.Monad: endTopSignature :: InferM TCTopEntity
+ Cryptol.TypeCheck.Monad: freshTParam :: (Name -> TPFlavor) -> TParam -> InferM TParam
+ Cryptol.TypeCheck.Monad: getCurDecls :: InferM (ModuleG ())
+ Cryptol.TypeCheck.Monad: getSignatures :: InferM (Map Name ModParamNames)
+ Cryptol.TypeCheck.Monad: lookupFunctor :: ImpName Name -> InferM (ModuleG ())
+ Cryptol.TypeCheck.Monad: lookupModParam :: Ident -> InferM (Maybe ModParam)
+ Cryptol.TypeCheck.Monad: lookupModule :: ImpName Name -> InferM (IfaceG ())
+ Cryptol.TypeCheck.Monad: lookupSignature :: ImpName Name -> InferM ModParamNames
+ Cryptol.TypeCheck.Monad: lookupTopModule :: ModName -> InferM (Maybe (ModuleG (), IfaceG ()))
+ Cryptol.TypeCheck.Monad: newLocalName :: Namespace -> Ident -> InferM Name
+ Cryptol.TypeCheck.Monad: newSignatureScope :: Name -> Maybe Text -> InferM ()
+ Cryptol.TypeCheck.Monad: newTopSignatureScope :: ModName -> InferM ()
+ Cryptol.TypeCheck.Monad: selectorScope :: InferM a -> InferM a
+ Cryptol.TypeCheck.Sanity: NotSame :: AreSame
+ Cryptol.TypeCheck.Sanity: SameIf :: [Prop] -> AreSame
+ Cryptol.TypeCheck.Sanity: data AreSame
+ Cryptol.TypeCheck.Sanity: instance (GHC.Classes.Eq a, Cryptol.TypeCheck.Sanity.Same b) => Cryptol.TypeCheck.Sanity.Same (Cryptol.TypeCheck.Sanity.Field a b)
+ Cryptol.TypeCheck.Sanity: instance Cryptol.Utils.PP.PP Cryptol.TypeCheck.Sanity.Error
+ Cryptol.TypeCheck.Sanity: onlyNonTrivial :: [ProofObligation] -> [ProofObligation]
+ Cryptol.TypeCheck.Solve: tryProveImplication :: Maybe Name -> [TParam] -> [Prop] -> [Goal] -> InferM Bool
+ Cryptol.TypeCheck.Solver.Numeric.Interval: ppIntervalsWithNames :: NameMap -> Map TVar Interval -> Doc
+ Cryptol.TypeCheck.Solver.SMT: assume :: Solver -> TVars -> Prop -> IO ()
+ Cryptol.TypeCheck.Solver.SMT: declareVars :: Solver -> [TVar] -> IO TVars
+ Cryptol.TypeCheck.Solver.SMT: inNewFrame :: Solver -> IO a -> IO a
+ Cryptol.TypeCheck.Solver.SMT: instance Cryptol.TypeCheck.Solver.SMT.Mk GHC.Num.Integer.Integer
+ Cryptol.TypeCheck.Solver.SMT: type TVars = Map TVar SExpr
+ Cryptol.TypeCheck.Solver.SMT: unsolvable :: Solver -> TVars -> [Prop] -> IO Bool
+ Cryptol.TypeCheck.Subst: instance Cryptol.TypeCheck.Subst.TVars (Cryptol.TypeCheck.AST.ModuleG names)
+ Cryptol.TypeCheck.Subst: instance Cryptol.TypeCheck.Subst.TVars Cryptol.TypeCheck.AST.TCTopEntity
+ Cryptol.TypeCheck.Subst: mergeDistinctSubst :: [Subst] -> Subst
+ Cryptol.TypeCheck.Type: ModParam :: Ident -> !Maybe ModName -> ImpName Name -> ModParamNames -> ModParam
+ Cryptol.TypeCheck.Type: ModParamNames :: Map Name ModTParam -> !Map Name TySyn -> [Located Prop] -> Map Name ModVParam -> !Maybe Text -> ModParamNames
+ Cryptol.TypeCheck.Type: [mpIface] :: ModParam -> ImpName Name
+ Cryptol.TypeCheck.Type: [mpName] :: ModParam -> Ident
+ Cryptol.TypeCheck.Type: [mpParameters] :: ModParam -> ModParamNames
+ Cryptol.TypeCheck.Type: [mpQual] :: ModParam -> !Maybe ModName
+ Cryptol.TypeCheck.Type: [mpnConstraints] :: ModParamNames -> [Located Prop]
+ Cryptol.TypeCheck.Type: [mpnDoc] :: ModParamNames -> !Maybe Text
+ Cryptol.TypeCheck.Type: [mpnFuns] :: ModParamNames -> Map Name ModVParam
+ Cryptol.TypeCheck.Type: [mpnTySyn] :: ModParamNames -> !Map Name TySyn
+ Cryptol.TypeCheck.Type: [mpnTypes] :: ModParamNames -> Map Name ModTParam
+ Cryptol.TypeCheck.Type: [ntConName] :: Newtype -> !Name
+ Cryptol.TypeCheck.Type: allParamNames :: FunctorParams -> ModParamNames
+ Cryptol.TypeCheck.Type: class FreeAbstract t
+ Cryptol.TypeCheck.Type: data ModParam
+ Cryptol.TypeCheck.Type: data ModParamNames
+ Cryptol.TypeCheck.Type: freeAbstract :: FreeAbstract t => t -> Set UserTC
+ Cryptol.TypeCheck.Type: instance (Cryptol.TypeCheck.Type.FreeAbstract a, Cryptol.TypeCheck.Type.FreeAbstract b) => Cryptol.TypeCheck.Type.FreeAbstract (a, b)
+ Cryptol.TypeCheck.Type: instance Control.DeepSeq.NFData Cryptol.TypeCheck.Type.ModParam
+ Cryptol.TypeCheck.Type: instance Control.DeepSeq.NFData Cryptol.TypeCheck.Type.ModParamNames
+ Cryptol.TypeCheck.Type: instance Cryptol.TypeCheck.TCon.HasKind Cryptol.TypeCheck.Type.AbstractType
+ Cryptol.TypeCheck.Type: instance Cryptol.TypeCheck.Type.FreeAbstract Cryptol.TypeCheck.TCon.TCon
+ Cryptol.TypeCheck.Type: instance Cryptol.TypeCheck.Type.FreeAbstract Cryptol.TypeCheck.Type.Type
+ Cryptol.TypeCheck.Type: instance Cryptol.TypeCheck.Type.FreeAbstract a => Cryptol.TypeCheck.Type.FreeAbstract [a]
+ Cryptol.TypeCheck.Type: instance Cryptol.Utils.PP.PP Cryptol.TypeCheck.Type.ModParamNames
+ Cryptol.TypeCheck.Type: instance Cryptol.Utils.PP.PP Cryptol.TypeCheck.Type.ModTParam
+ Cryptol.TypeCheck.Type: instance Cryptol.Utils.PP.PP Cryptol.TypeCheck.Type.ModVParam
+ Cryptol.TypeCheck.Type: instance GHC.Generics.Generic Cryptol.TypeCheck.Type.ModParam
+ Cryptol.TypeCheck.Type: instance GHC.Generics.Generic Cryptol.TypeCheck.Type.ModParamNames
+ Cryptol.TypeCheck.Type: instance GHC.Show.Show Cryptol.TypeCheck.Type.ModParam
+ Cryptol.TypeCheck.Type: instance GHC.Show.Show Cryptol.TypeCheck.Type.ModParamNames
+ Cryptol.TypeCheck.Type: pNegNumeric :: Prop -> [Prop]
+ Cryptol.TypeCheck.Type: ppNewtypeFull :: Newtype -> Doc
+ Cryptol.TypeCheck.Type: type FunctorParams = Map Ident ModParam
+ Cryptol.TypeCheck.TypePat: anAbstractType :: Pat Type UserTC
+ Cryptol.Utils.Benchmark: BenchmarkStats :: !Double -> !Double -> !Int64 -> BenchmarkStats
+ Cryptol.Utils.Benchmark: [benchAvgCpuTime] :: BenchmarkStats -> !Double
+ Cryptol.Utils.Benchmark: [benchAvgCycles] :: BenchmarkStats -> !Int64
+ Cryptol.Utils.Benchmark: [benchAvgTime] :: BenchmarkStats -> !Double
+ Cryptol.Utils.Benchmark: benchmark :: Double -> (a -> IO b) -> a -> IO BenchmarkStats
+ Cryptol.Utils.Benchmark: data BenchmarkStats
+ Cryptol.Utils.Benchmark: instance GHC.Show.Show Cryptol.Utils.Benchmark.BenchmarkStats
+ Cryptol.Utils.Benchmark: secs :: Double -> String
+ Cryptol.Utils.Fixity: instance GHC.Classes.Ord Cryptol.Utils.Fixity.Assoc
+ Cryptol.Utils.Fixity: instance GHC.Classes.Ord Cryptol.Utils.Fixity.Fixity
+ Cryptol.Utils.Ident: FromDefinition :: OrigSource
+ Cryptol.Utils.Ident: FromFunctorInst :: OrigSource
+ Cryptol.Utils.Ident: FromModParam :: Ident -> OrigSource
+ Cryptol.Utils.Ident: [ogSource] :: OrigName -> OrigSource
+ Cryptol.Utils.Ident: data OrigSource
+ Cryptol.Utils.Ident: identAnonArg :: Ident -> Ident
+ Cryptol.Utils.Ident: identAnonIfaceMod :: Ident -> Ident
+ Cryptol.Utils.Ident: identIsNormal :: Ident -> Bool
+ Cryptol.Utils.Ident: instance Control.DeepSeq.NFData Cryptol.Utils.Ident.MaybeAnon
+ Cryptol.Utils.Ident: instance Control.DeepSeq.NFData Cryptol.Utils.Ident.OrigSource
+ Cryptol.Utils.Ident: instance GHC.Classes.Eq Cryptol.Utils.Ident.MaybeAnon
+ Cryptol.Utils.Ident: instance GHC.Classes.Eq Cryptol.Utils.Ident.OrigSource
+ Cryptol.Utils.Ident: instance GHC.Classes.Ord Cryptol.Utils.Ident.MaybeAnon
+ Cryptol.Utils.Ident: instance GHC.Classes.Ord Cryptol.Utils.Ident.OrigSource
+ Cryptol.Utils.Ident: instance GHC.Generics.Generic Cryptol.Utils.Ident.MaybeAnon
+ Cryptol.Utils.Ident: instance GHC.Generics.Generic Cryptol.Utils.Ident.OrigSource
+ Cryptol.Utils.Ident: instance GHC.Show.Show Cryptol.Utils.Ident.MaybeAnon
+ Cryptol.Utils.Ident: instance GHC.Show.Show Cryptol.Utils.Ident.OrigSource
+ Cryptol.Utils.Ident: modNameArg :: ModName -> ModName
+ Cryptol.Utils.Ident: modNameChunksText :: ModName -> [Text]
+ Cryptol.Utils.Ident: modNameIfaceMod :: ModName -> ModName
+ Cryptol.Utils.Ident: modNameIsNormal :: ModName -> Bool
+ Cryptol.Utils.Ident: modNameToNormalModName :: ModName -> ModName
+ Cryptol.Utils.Ident: modPathIsNormal :: ModPath -> Bool
+ Cryptol.Utils.Ident: modPathIsOrContains :: ModPath -> ModPath -> Bool
+ Cryptol.Utils.Ident: ogFromModParam :: OrigName -> Bool
+ Cryptol.Utils.Ident: undefinedModName :: ModName
+ Cryptol.Utils.PP: PPCfg :: NameDisp -> Bool -> PPCfg
+ Cryptol.Utils.PP: [ppcfgNameDisp] :: PPCfg -> NameDisp
+ Cryptol.Utils.PP: [ppcfgShowNameUniques] :: PPCfg -> Bool
+ Cryptol.Utils.PP: data PPCfg
+ Cryptol.Utils.PP: debugShowUniques :: Doc -> Doc
+ Cryptol.Utils.PP: defaultPPCfg :: PPCfg
+ Cryptol.Utils.PP: fixPPCfg :: PPCfg -> Doc -> Doc
+ Cryptol.Utils.PP: instance Cryptol.Utils.PP.PP Cryptol.Utils.Ident.PrimIdent
+ Cryptol.Utils.PP: pipe :: Doc
+ Cryptol.Utils.PP: reflow :: Text -> Doc
+ Cryptol.Utils.PP: runDocWith :: PPCfg -> Doc -> Doc Void
+ Cryptol.Utils.PP: updPPCfg :: (PPCfg -> PPCfg) -> Doc -> Doc
+ Cryptol.Utils.PP: withPPCfg :: (PPCfg -> Doc) -> Doc
+ Cryptol.Utils.Panic: xxxTODO :: HasCallStack => String -> a
+ Cryptol.Utils.RecordMap: displayElements :: (Show a, Ord a) => RecordMap a b -> [b]
+ Cryptol.Utils.Types: float32ExpPrec :: (Integer, Integer)
+ Cryptol.Utils.Types: float64ExpPrec :: (Integer, Integer)
- Cryptol.ModuleSystem: Iface :: !mname -> IfaceDecls -> IfaceDecls -> IfaceParams -> IfaceG mname
+ Cryptol.ModuleSystem: Iface :: IfaceNames name -> FunctorParams -> IfaceDecls -> IfaceG name
- Cryptol.ModuleSystem: IfaceDecl :: !Name -> Schema -> [Pragma] -> Bool -> Maybe Fixity -> Maybe Text -> IfaceDecl
+ Cryptol.ModuleSystem: IfaceDecl :: !Name -> Schema -> !Bool -> [Pragma] -> Bool -> Maybe Fixity -> Maybe Text -> IfaceDecl
- Cryptol.ModuleSystem: IfaceDecls :: Map Name IfaceTySyn -> Map Name IfaceNewtype -> Map Name IfaceAbstractType -> Map Name IfaceDecl -> !Map Name (IfaceG Name) -> IfaceDecls
+ Cryptol.ModuleSystem: IfaceDecls :: Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> Map Name IfaceDecl -> !Map Name (IfaceNames Name) -> !Map Name ModParamNames -> !Map Name (IfaceG Name) -> IfaceDecls
- Cryptol.ModuleSystem: [ifAbstractTypes] :: IfaceDecls -> Map Name IfaceAbstractType
+ Cryptol.ModuleSystem: [ifAbstractTypes] :: IfaceDecls -> Map Name AbstractType
- Cryptol.ModuleSystem: [ifModules] :: IfaceDecls -> !Map Name (IfaceG Name)
+ Cryptol.ModuleSystem: [ifModules] :: IfaceDecls -> !Map Name (IfaceNames Name)
- Cryptol.ModuleSystem: [ifNewtypes] :: IfaceDecls -> Map Name IfaceNewtype
+ Cryptol.ModuleSystem: [ifNewtypes] :: IfaceDecls -> Map Name Newtype
- Cryptol.ModuleSystem: [ifParams] :: IfaceG mname -> IfaceParams
+ Cryptol.ModuleSystem: [ifParams] :: IfaceG name -> FunctorParams
- Cryptol.ModuleSystem: [ifTySyns] :: IfaceDecls -> Map Name IfaceTySyn
+ Cryptol.ModuleSystem: [ifTySyns] :: IfaceDecls -> Map Name TySyn
- Cryptol.ModuleSystem: data IfaceG mname
+ Cryptol.ModuleSystem: data IfaceG name
- Cryptol.ModuleSystem: genIface :: ModuleG mname -> IfaceG mname
+ Cryptol.ModuleSystem: genIface :: ModuleG name -> IfaceG name
- Cryptol.ModuleSystem: loadModuleByName :: ModName -> ModuleCmd (ModulePath, Module)
+ Cryptol.ModuleSystem: loadModuleByName :: ModName -> ModuleCmd (ModulePath, TCTopEntity)
- Cryptol.ModuleSystem: loadModuleByPath :: FilePath -> ModuleCmd (ModulePath, Module)
+ Cryptol.ModuleSystem: loadModuleByPath :: FilePath -> ModuleCmd (ModulePath, TCTopEntity)
- Cryptol.ModuleSystem.Base: checkModule :: ImportSource -> Module PName -> ModuleM (NamingEnv, Module)
+ Cryptol.ModuleSystem.Base: checkModule :: ImportSource -> Module PName -> ModuleM (NamingEnv, TCTopEntity)
- Cryptol.ModuleSystem.Base: doLoadModule :: Bool -> ImportSource -> ModulePath -> Fingerprint -> Module PName -> ModuleM Module
+ Cryptol.ModuleSystem.Base: doLoadModule :: Bool -> Bool -> ImportSource -> ModulePath -> Fingerprint -> Set FilePath -> Module PName -> ModuleM TCTopEntity
- Cryptol.ModuleSystem.Base: genInferInput :: Range -> PrimMap -> IfaceParams -> IfaceDecls -> ModuleM InferInput
+ Cryptol.ModuleSystem.Base: genInferInput :: Range -> PrimMap -> ModContextParams -> IfaceDecls -> ModuleM InferInput
- Cryptol.ModuleSystem.Base: loadDeps :: Module name -> ModuleM ()
+ Cryptol.ModuleSystem.Base: loadDeps :: ModuleG mname name -> ModuleM (Set ModName)
- Cryptol.ModuleSystem.Base: loadModuleByPath :: FilePath -> ModuleM Module
+ Cryptol.ModuleSystem.Base: loadModuleByPath :: Bool -> FilePath -> ModuleM TCTopEntity
- Cryptol.ModuleSystem.Base: loadModuleFrom :: Bool -> ImportSource -> ModuleM (ModulePath, Module)
+ Cryptol.ModuleSystem.Base: loadModuleFrom :: Bool -> ImportSource -> ModuleM (ModulePath, TCTopEntity)
- Cryptol.ModuleSystem.Base: parseModule :: ModulePath -> ModuleM (Fingerprint, Module PName)
+ Cryptol.ModuleSystem.Base: parseModule :: ModulePath -> ModuleM (Fingerprint, Set FilePath, [Module PName])
- Cryptol.ModuleSystem.Base: typecheck :: (Show i, Show o, HasLoc i) => TCAction i o -> i -> IfaceParams -> IfaceDecls -> ModuleM o
+ Cryptol.ModuleSystem.Base: typecheck :: (Show i, Show o, HasLoc i) => TCAction i o -> i -> ModContextParams -> IfaceDecls -> ModuleM o
- Cryptol.ModuleSystem.Env: LoadedModule :: ModName -> ModulePath -> String -> !NamingEnv -> Iface -> Module -> Fingerprint -> LoadedModule
+ Cryptol.ModuleSystem.Env: LoadedModule :: ModName -> ModulePath -> String -> !NamingEnv -> !FileInfo -> a -> LoadedModuleG a
- Cryptol.ModuleSystem.Env: LoadedModules :: [LoadedModule] -> [LoadedModule] -> LoadedModules
+ Cryptol.ModuleSystem.Env: LoadedModules :: [LoadedModule] -> [LoadedModule] -> ![LoadedSignature] -> LoadedModules
- Cryptol.ModuleSystem.Env: ModContext :: IfaceParams -> Set Name -> IfaceDecls -> NamingEnv -> NameDisp -> ModContext
+ Cryptol.ModuleSystem.Env: ModContext :: ModContextParams -> Set Name -> IfaceDecls -> NamingEnv -> NameDisp -> ModContext
- Cryptol.ModuleSystem.Env: [lmFilePath] :: LoadedModule -> ModulePath
+ Cryptol.ModuleSystem.Env: [lmFilePath] :: LoadedModuleG a -> ModulePath
- Cryptol.ModuleSystem.Env: [lmModuleId] :: LoadedModule -> String
+ Cryptol.ModuleSystem.Env: [lmModuleId] :: LoadedModuleG a -> String
- Cryptol.ModuleSystem.Env: [lmName] :: LoadedModule -> ModName
+ Cryptol.ModuleSystem.Env: [lmName] :: LoadedModuleG a -> ModName
- Cryptol.ModuleSystem.Env: [lmNamingEnv] :: LoadedModule -> !NamingEnv
+ Cryptol.ModuleSystem.Env: [lmNamingEnv] :: LoadedModuleG a -> !NamingEnv
- Cryptol.ModuleSystem.Env: [mctxParams] :: ModContext -> IfaceParams
+ Cryptol.ModuleSystem.Env: [mctxParams] :: ModContext -> ModContextParams
- Cryptol.ModuleSystem.Env: addLoadedModule :: ModulePath -> String -> Fingerprint -> NamingEnv -> Module -> LoadedModules -> LoadedModules
+ Cryptol.ModuleSystem.Env: addLoadedModule :: ModulePath -> String -> FileInfo -> NamingEnv -> Maybe ForeignSrc -> Module -> LoadedModules -> LoadedModules
- Cryptol.ModuleSystem.Env: loadedNewtypes :: ModuleEnv -> Map Name IfaceNewtype
+ Cryptol.ModuleSystem.Env: loadedNewtypes :: ModuleEnv -> Map Name Newtype
- Cryptol.ModuleSystem.Env: removeLoadedModule :: (LoadedModule -> Bool) -> LoadedModules -> LoadedModules
+ Cryptol.ModuleSystem.Env: removeLoadedModule :: (forall a. LoadedModuleG a -> Bool) -> LoadedModules -> LoadedModules
- Cryptol.ModuleSystem.Env: resetModuleEnv :: ModuleEnv -> ModuleEnv
+ Cryptol.ModuleSystem.Env: resetModuleEnv :: ModuleEnv -> IO ModuleEnv
- Cryptol.ModuleSystem.Interface: Iface :: !mname -> IfaceDecls -> IfaceDecls -> IfaceParams -> IfaceG mname
+ Cryptol.ModuleSystem.Interface: Iface :: IfaceNames name -> FunctorParams -> IfaceDecls -> IfaceG name
- Cryptol.ModuleSystem.Interface: IfaceDecl :: !Name -> Schema -> [Pragma] -> Bool -> Maybe Fixity -> Maybe Text -> IfaceDecl
+ Cryptol.ModuleSystem.Interface: IfaceDecl :: !Name -> Schema -> !Bool -> [Pragma] -> Bool -> Maybe Fixity -> Maybe Text -> IfaceDecl
- Cryptol.ModuleSystem.Interface: IfaceDecls :: Map Name IfaceTySyn -> Map Name IfaceNewtype -> Map Name IfaceAbstractType -> Map Name IfaceDecl -> !Map Name (IfaceG Name) -> IfaceDecls
+ Cryptol.ModuleSystem.Interface: IfaceDecls :: Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> Map Name IfaceDecl -> !Map Name (IfaceNames Name) -> !Map Name ModParamNames -> !Map Name (IfaceG Name) -> IfaceDecls
- Cryptol.ModuleSystem.Interface: [ifAbstractTypes] :: IfaceDecls -> Map Name IfaceAbstractType
+ Cryptol.ModuleSystem.Interface: [ifAbstractTypes] :: IfaceDecls -> Map Name AbstractType
- Cryptol.ModuleSystem.Interface: [ifModules] :: IfaceDecls -> !Map Name (IfaceG Name)
+ Cryptol.ModuleSystem.Interface: [ifModules] :: IfaceDecls -> !Map Name (IfaceNames Name)
- Cryptol.ModuleSystem.Interface: [ifNewtypes] :: IfaceDecls -> Map Name IfaceNewtype
+ Cryptol.ModuleSystem.Interface: [ifNewtypes] :: IfaceDecls -> Map Name Newtype
- Cryptol.ModuleSystem.Interface: [ifParams] :: IfaceG mname -> IfaceParams
+ Cryptol.ModuleSystem.Interface: [ifParams] :: IfaceG name -> FunctorParams
- Cryptol.ModuleSystem.Interface: [ifTySyns] :: IfaceDecls -> Map Name IfaceTySyn
+ Cryptol.ModuleSystem.Interface: [ifTySyns] :: IfaceDecls -> Map Name TySyn
- Cryptol.ModuleSystem.Interface: data IfaceG mname
+ Cryptol.ModuleSystem.Interface: data IfaceG name
- Cryptol.ModuleSystem.Interface: emptyIface :: mname -> IfaceG mname
+ Cryptol.ModuleSystem.Interface: emptyIface :: ModName -> Iface
- Cryptol.ModuleSystem.Interface: ifaceIsFunctor :: IfaceG mname -> Bool
+ Cryptol.ModuleSystem.Interface: ifaceIsFunctor :: IfaceG name -> Bool
- Cryptol.ModuleSystem.Monad: getIfaces :: ModuleM (ModName -> Iface)
+ Cryptol.ModuleSystem.Monad: getIfaces :: ModuleM (Map ModName (Either ModParamNames Iface))
- Cryptol.ModuleSystem.Monad: getLoadedMaybe :: ModName -> ModuleM (Maybe LoadedModule)
+ Cryptol.ModuleSystem.Monad: getLoadedMaybe :: ModName -> ModuleM (Maybe (LoadedModuleG TCTopEntity))
- Cryptol.ModuleSystem.Monad: loadedModule :: ModulePath -> Fingerprint -> NamingEnv -> Module -> ModuleM ()
+ Cryptol.ModuleSystem.Monad: loadedModule :: ModulePath -> FileInfo -> NamingEnv -> Maybe ForeignSrc -> TCTopEntity -> ModuleM ()
- Cryptol.ModuleSystem.Monad: unloadModule :: (LoadedModule -> Bool) -> ModuleM ()
+ Cryptol.ModuleSystem.Monad: unloadModule :: (forall a. LoadedModuleG a -> Bool) -> ModuleM ()
- Cryptol.ModuleSystem.NamingEnv: NamingEnv :: Map Namespace (Map PName [Name]) -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: NamingEnv :: Map Namespace (Map PName Names) -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: lookupNS :: Namespace -> PName -> NamingEnv -> [Name]
+ Cryptol.ModuleSystem.NamingEnv: lookupNS :: Namespace -> PName -> NamingEnv -> Maybe Names
- Cryptol.ModuleSystem.NamingEnv: modParamsNamingEnv :: IfaceParams -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: modParamsNamingEnv :: ModParamNames -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: namespaceMap :: Namespace -> NamingEnv -> Map PName [Name]
+ Cryptol.ModuleSystem.NamingEnv: namespaceMap :: Namespace -> NamingEnv -> Map PName Names
- Cryptol.ModuleSystem.Renamer: RenamerInfo :: Supply -> ModPath -> NamingEnv -> (ModName -> Iface) -> RenamerInfo
+ Cryptol.ModuleSystem.Renamer: RenamerInfo :: Supply -> ModPath -> NamingEnv -> Map ModName (Either ModParamNames Iface) -> RenamerInfo
- Cryptol.ModuleSystem.Renamer: [renIfaces] :: RenamerInfo -> ModName -> Iface
+ Cryptol.ModuleSystem.Renamer: [renIfaces] :: RenamerInfo -> Map ModName (Either ModParamNames Iface)
- Cryptol.ModuleSystem.Renamer.Error: depNameLoc :: DepName -> Range
+ Cryptol.ModuleSystem.Renamer.Error: depNameLoc :: DepName -> Maybe Range
- Cryptol.ModuleSystem.Renamer.Monad: RO :: Range -> NamingEnv -> (ModName -> Iface) -> ModPath -> Map ModPath Name -> RO
+ Cryptol.ModuleSystem.Renamer.Monad: RO :: Range -> NamingEnv -> Map ModName (Maybe Iface, Map (ImpName Name) (Mod ())) -> ModPath -> Map ModPath Name -> Map (ImpName Name) ResolvedLocal -> Map Ident RenModParam -> Map Name DepName -> RO
- Cryptol.ModuleSystem.Renamer.Monad: RW :: ![RenamerWarning] -> !Seq RenamerError -> !Supply -> !Map Name Int -> Set Name -> Map DepName (Set Name) -> !IfaceDecls -> RW
+ Cryptol.ModuleSystem.Renamer.Monad: RW :: ![RenamerWarning] -> !Set RenamerError -> !Supply -> !Map Name Int -> Set Name -> Map DepName (Set Name) -> !IfaceDecls -> RW
- Cryptol.ModuleSystem.Renamer.Monad: RenamerInfo :: Supply -> ModPath -> NamingEnv -> (ModName -> Iface) -> RenamerInfo
+ Cryptol.ModuleSystem.Renamer.Monad: RenamerInfo :: Supply -> ModPath -> NamingEnv -> Map ModName (Either ModParamNames Iface) -> RenamerInfo
- Cryptol.ModuleSystem.Renamer.Monad: [renIfaces] :: RenamerInfo -> ModName -> Iface
+ Cryptol.ModuleSystem.Renamer.Monad: [renIfaces] :: RenamerInfo -> Map ModName (Either ModParamNames Iface)
- Cryptol.ModuleSystem.Renamer.Monad: [rwErrors] :: RW -> !Seq RenamerError
+ Cryptol.ModuleSystem.Renamer.Monad: [rwErrors] :: RW -> !Set RenamerError
- Cryptol.Parser: parseModule :: Config -> Text -> Either ParseError (Module PName)
+ Cryptol.Parser: parseModule :: Config -> Text -> Either ParseError [Module PName]
- Cryptol.Parser.AST: DParameterConstraint :: [Located (Prop name)] -> TopDecl name
+ Cryptol.Parser.AST: DParameterConstraint :: [Located (Prop name)] -> ParamDecl name
- Cryptol.Parser.AST: DParameterFun :: ParameterFun name -> TopDecl name
+ Cryptol.Parser.AST: DParameterFun :: ParameterFun name -> ParamDecl name
- Cryptol.Parser.AST: DParameterType :: ParameterType name -> TopDecl name
+ Cryptol.Parser.AST: DParameterType :: ParameterType name -> ParamDecl name
- Cryptol.Parser.AST: Import :: !mname -> Maybe ModName -> Maybe ImportSpec -> ImportG mname
+ Cryptol.Parser.AST: Import :: !mname -> Maybe ModName -> Maybe ImportSpec -> !Maybe (ModuleInstanceArgs PName) -> ImportG mname
- Cryptol.Parser.AST: Module :: Located mname -> !Maybe (Located ModName) -> [TopDecl name] -> ModuleG mname name
+ Cryptol.Parser.AST: Module :: Located mname -> ModuleDefinition name -> ModuleG mname name
- Cryptol.Parser.AST: Newtype :: Located name -> [TParam name] -> Rec (Type name) -> Newtype name
+ Cryptol.Parser.AST: Newtype :: Located name -> [TParam name] -> !name -> Rec (Type name) -> Newtype name
- Cryptol.Parser.AST: TParens :: Type n -> Type n
+ Cryptol.Parser.AST: TParens :: Type n -> Maybe Kind -> Type n
- Cryptol.Parser.NoInclude: removeIncludesModule :: (FilePath -> IO ByteString) -> FilePath -> Module PName -> IO (Either [IncludeError] (Module PName))
+ Cryptol.Parser.NoInclude: removeIncludesModule :: (FilePath -> IO ByteString) -> FilePath -> Module PName -> IO (Either [IncludeError] (Module PName, Set FilePath))
- Cryptol.PrimeEC: bigNatToInteger :: BigNat -> Integer
+ Cryptol.PrimeEC: bigNatToInteger :: BigNat# -> Integer
- Cryptol.REPL.Monad: EvalInParamModule :: [Name] -> REPLException
+ Cryptol.REPL.Monad: EvalInParamModule :: [TParam] -> [Name] -> REPLException
- Cryptol.TypeCheck: InferInput :: Range -> Map Name Schema -> Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> !Map Name ModTParam -> ![Located Prop] -> !Map Name ModVParam -> NameSeeds -> Bool -> Bool -> [FilePath] -> !PrimMap -> !Supply -> Solver -> InferInput
+ Cryptol.TypeCheck: InferInput :: Range -> Map Name Schema -> Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> !Map Name ModParamNames -> (ModName -> Maybe (ModuleG (), IfaceG ())) -> (ModName -> Maybe ModParamNames) -> !ModParamNames -> NameSeeds -> Bool -> Bool -> [FilePath] -> !PrimMap -> !Supply -> Solver -> InferInput
- Cryptol.TypeCheck: tcModule :: Module Name -> InferInput -> IO (InferOutput Module)
+ Cryptol.TypeCheck: tcModule :: Module Name -> InferInput -> IO (InferOutput TCTopEntity)
- Cryptol.TypeCheck.AST: Import :: !mname -> Maybe ModName -> Maybe ImportSpec -> ImportG mname
+ Cryptol.TypeCheck.AST: Import :: !mname -> Maybe ModName -> Maybe ImportSpec -> !Maybe (ModuleInstanceArgs PName) -> ImportG mname
- Cryptol.TypeCheck.AST: Module :: !mname -> ExportSpec Name -> [Import] -> Map Name (IfaceG Name) -> Map Name ModTParam -> [Located Prop] -> Map Name ModVParam -> Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> [DeclGroup] -> Map Name (ModuleG Name) -> ModuleG mname
+ Cryptol.TypeCheck.AST: Module :: !mname -> !Maybe Text -> ExportSpec Name -> Map Name ModTParam -> Map Name ModVParam -> [Located Prop] -> FunctorParams -> Map Name (ModuleG Name) -> !Set Name -> Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> [DeclGroup] -> Map Name (IfaceNames Name) -> !Map Name ModParamNames -> ModuleG mname
- Cryptol.TypeCheck.InferTypes: CtModuleInstance :: ModName -> ConstraintSource
+ Cryptol.TypeCheck.InferTypes: CtModuleInstance :: Range -> ConstraintSource
- Cryptol.TypeCheck.Interface: genIface :: ModuleG mname -> IfaceG mname
+ Cryptol.TypeCheck.Interface: genIface :: ModuleG name -> IfaceG name
- Cryptol.TypeCheck.Kind: checkParameterType :: ParameterType Name -> Maybe Text -> InferM ModTParam
+ Cryptol.TypeCheck.Kind: checkParameterType :: ParameterType Name -> InferM ModTParam
- Cryptol.TypeCheck.Monad: IM :: ReaderT RO (StateT RW IO) a -> InferM a
+ Cryptol.TypeCheck.Monad: IM :: ReaderT RO (StateT RW (ExceptionT [(Range, Error)] IO)) a -> InferM a
- Cryptol.TypeCheck.Monad: InferInput :: Range -> Map Name Schema -> Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> !Map Name ModTParam -> ![Located Prop] -> !Map Name ModVParam -> NameSeeds -> Bool -> Bool -> [FilePath] -> !PrimMap -> !Supply -> Solver -> InferInput
+ Cryptol.TypeCheck.Monad: InferInput :: Range -> Map Name Schema -> Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> !Map Name ModParamNames -> (ModName -> Maybe (ModuleG (), IfaceG ())) -> (ModName -> Maybe ModParamNames) -> !ModParamNames -> NameSeeds -> Bool -> Bool -> [FilePath] -> !PrimMap -> !Supply -> Solver -> InferInput
- Cryptol.TypeCheck.Monad: RO :: Range -> Map Name VarType -> [TParam] -> ModuleG ScopeName -> Map Int HasGoalSln -> Bool -> Bool -> Solver -> !PrimMap -> !IORef Int -> RO
+ Cryptol.TypeCheck.Monad: RO :: Range -> Map Name VarType -> [TParam] -> (ModName -> Maybe (ModuleG (), IfaceG ())) -> (ModName -> Maybe ModParamNames) -> ModuleG ScopeName -> Map Int HasGoalSln -> Bool -> Bool -> Solver -> !PrimMap -> !IORef Int -> RO
- Cryptol.TypeCheck.Monad: RW :: ![(Range, Error)] -> ![(Range, Warning)] -> !Subst -> [Map Name Type] -> Map Int HasGoalSln -> !NameSeeds -> !Goals -> ![HasGoal] -> ![ModuleG ScopeName] -> !Map Name Schema -> !Supply -> RW
+ Cryptol.TypeCheck.Monad: RW :: ![(Range, Error)] -> ![(Range, Warning)] -> !Subst -> [Map Name Type] -> Map Int HasGoalSln -> !NameSeeds -> !Goals -> ![[HasGoal]] -> ![ModuleG ScopeName] -> !Map Name Schema -> !Supply -> RW
- Cryptol.TypeCheck.Monad: [iHasCts] :: RW -> ![HasGoal]
+ Cryptol.TypeCheck.Monad: [iHasCts] :: RW -> ![[HasGoal]]
- Cryptol.TypeCheck.Monad: [unIM] :: InferM a -> ReaderT RO (StateT RW IO) a
+ Cryptol.TypeCheck.Monad: [unIM] :: InferM a -> ReaderT RO (StateT RW (ExceptionT [(Range, Error)] IO)) a
- Cryptol.TypeCheck.Monad: endModule :: InferM Module
+ Cryptol.TypeCheck.Monad: endModule :: InferM TCTopEntity
- Cryptol.TypeCheck.Monad: newModuleScope :: ModName -> [Import] -> ExportSpec Name -> InferM ()
+ Cryptol.TypeCheck.Monad: newModuleScope :: ModName -> ExportSpec Name -> InferM ()
- Cryptol.TypeCheck.Monad: newSubmoduleScope :: Name -> [Import] -> ExportSpec Name -> InferM ()
+ Cryptol.TypeCheck.Monad: newSubmoduleScope :: Name -> Maybe Text -> ExportSpec Name -> InferM ()
- Cryptol.TypeCheck.Sanity: same :: Same a => a -> a -> Bool
+ Cryptol.TypeCheck.Sanity: same :: Same a => a -> a -> AreSame
- Cryptol.TypeCheck.Solve: proveImplication :: Maybe Name -> [TParam] -> [Prop] -> [Goal] -> InferM Subst
+ Cryptol.TypeCheck.Solve: proveImplication :: Bool -> Maybe Name -> [TParam] -> [Prop] -> [Goal] -> InferM Subst
- Cryptol.TypeCheck.Type: ModTParam :: Name -> Kind -> !Int -> Maybe Text -> ModTParam
+ Cryptol.TypeCheck.Type: ModTParam :: Name -> Kind -> Maybe Text -> ModTParam
- Cryptol.TypeCheck.Type: Newtype :: Name -> [TParam] -> [Prop] -> RecordMap Ident Type -> Maybe Text -> Newtype
+ Cryptol.TypeCheck.Type: Newtype :: Name -> [TParam] -> [Prop] -> !Name -> RecordMap Ident Type -> Maybe Text -> Newtype
- Cryptol.Utils.Ident: OrigName :: Namespace -> ModPath -> Ident -> OrigName
+ Cryptol.Utils.Ident: OrigName :: Namespace -> ModPath -> OrigSource -> Ident -> OrigName
- Cryptol.Utils.PP: Doc :: (NameDisp -> Doc Void) -> Doc
+ Cryptol.Utils.PP: Doc :: (PPCfg -> Doc Void) -> Doc
Files
- CHANGES.md +100/−0
- bench/Main.hs +1/−2
- cryptol.cabal +45/−9
- cryptol/CheckExercises.hs +2/−1
- cryptol/Main.hs +1/−1
- lib/Array.cry +1/−0
- lib/Cryptol.cry +15/−5
- src/Cryptol/Backend/FFI.hs +276/−0
- src/Cryptol/Backend/FFI/Error.hs +44/−0
- src/Cryptol/Backend/FloatHelpers.hs +6/−0
- src/Cryptol/Backend/Monad.hs +27/−11
- src/Cryptol/Backend/What4.hs +1/−0
- src/Cryptol/Eval.hs +77/−10
- src/Cryptol/Eval/Concrete.hs +1/−7
- src/Cryptol/Eval/FFI.hs +430/−0
- src/Cryptol/Eval/FFI/GenHeader.hs +196/−0
- src/Cryptol/Eval/Generic.hs +16/−16
- src/Cryptol/Eval/Reference.lhs +26/−4
- src/Cryptol/Eval/SBV.hs +1/−0
- src/Cryptol/Eval/Type.hs +7/−1
- src/Cryptol/Eval/What4.hs +8/−10
- src/Cryptol/IR/FreeVars.hs +2/−0
- src/Cryptol/IR/TraverseNames.hs +267/−0
- src/Cryptol/ModuleSystem.hs +47/−11
- src/Cryptol/ModuleSystem/Base.hs +354/−148
- src/Cryptol/ModuleSystem/Binds.hs +434/−0
- src/Cryptol/ModuleSystem/Env.hs +209/−37
- src/Cryptol/ModuleSystem/Exports.hs +25/−19
- src/Cryptol/ModuleSystem/Fingerprint.hs +12/−0
- src/Cryptol/ModuleSystem/InstantiateModule.hs +0/−325
- src/Cryptol/ModuleSystem/Interface.hs +114/−78
- src/Cryptol/ModuleSystem/Monad.hs +88/−56
- src/Cryptol/ModuleSystem/Name.hs +155/−76
- src/Cryptol/ModuleSystem/Names.hs +88/−0
- src/Cryptol/ModuleSystem/NamingEnv.hs +167/−331
- src/Cryptol/ModuleSystem/Renamer.hs +708/−289
- src/Cryptol/ModuleSystem/Renamer/Error.hs +98/−42
- src/Cryptol/ModuleSystem/Renamer/ImplicitImports.hs +114/−0
- src/Cryptol/ModuleSystem/Renamer/Imports.hs +576/−0
- src/Cryptol/ModuleSystem/Renamer/Monad.hs +247/−80
- src/Cryptol/Parser.y +138/−81
- src/Cryptol/Parser/AST.hs +474/−76
- src/Cryptol/Parser/ExpandPropGuards.hs +137/−0
- src/Cryptol/Parser/Layout.hs +5/−1
- src/Cryptol/Parser/Lexer.x +2/−2
- src/Cryptol/Parser/Name.hs +5/−2
- src/Cryptol/Parser/Names.hs +17/−5
- src/Cryptol/Parser/NoInclude.hs +53/−14
- src/Cryptol/Parser/NoPat.hs +33/−32
- src/Cryptol/Parser/ParserUtils.hs +526/−50
- src/Cryptol/Parser/Position.hs +5/−0
- src/Cryptol/Parser/Token.hs +3/−1
- src/Cryptol/Parser/Unlit.hs +34/−2
- src/Cryptol/Parser/Utils.hs +2/−1
- src/Cryptol/REPL/Browse.hs +48/−19
- src/Cryptol/REPL/Command.hs +279/−224
- src/Cryptol/REPL/Help.hs +379/−0
- src/Cryptol/REPL/Monad.hs +67/−12
- src/Cryptol/Symbolic.hs +1/−1
- src/Cryptol/Symbolic/SBV.hs +19/−4
- src/Cryptol/Symbolic/What4.hs +41/−20
- src/Cryptol/Testing/Random.hs +29/−9
- src/Cryptol/Transform/AddModParams.hs +0/−314
- src/Cryptol/Transform/MonoValues.hs +11/−7
- src/Cryptol/Transform/Specialize.hs +21/−5
- src/Cryptol/TypeCheck.hs +3/−29
- src/Cryptol/TypeCheck/AST.hs +135/−35
- src/Cryptol/TypeCheck/CheckModuleInstance.hs +0/−201
- src/Cryptol/TypeCheck/Default.hs +2/−0
- src/Cryptol/TypeCheck/Error.hs +188/−4
- src/Cryptol/TypeCheck/FFI.hs +112/−0
- src/Cryptol/TypeCheck/FFI/Error.hs +83/−0
- src/Cryptol/TypeCheck/FFI/FFIType.hs +70/−0
- src/Cryptol/TypeCheck/Infer.hs +441/−106
- src/Cryptol/TypeCheck/InferTypes.hs +12/−4
- src/Cryptol/TypeCheck/Interface.hs +57/−47
- src/Cryptol/TypeCheck/Kind.hs +44/−14
- src/Cryptol/TypeCheck/Module.hs +376/−0
- src/Cryptol/TypeCheck/ModuleBacktickInstance.hs +408/−0
- src/Cryptol/TypeCheck/ModuleInstance.hs +168/−0
- src/Cryptol/TypeCheck/Monad.hs +402/−92
- src/Cryptol/TypeCheck/Parseable.hs +3/−0
- src/Cryptol/TypeCheck/Sanity.hs +209/−23
- src/Cryptol/TypeCheck/SimpType.hs +1/−0
- src/Cryptol/TypeCheck/Solve.hs +31/−9
- src/Cryptol/TypeCheck/Solver/Class.hs +1/−0
- src/Cryptol/TypeCheck/Solver/Improve.hs +2/−0
- src/Cryptol/TypeCheck/Solver/Numeric/Interval.hs +10/−0
- src/Cryptol/TypeCheck/Solver/SMT.hs +16/−4
- src/Cryptol/TypeCheck/Solver/Selector.hs +7/−7
- src/Cryptol/TypeCheck/Solver/Types.hs +1/−0
- src/Cryptol/TypeCheck/Subst.hs +79/−23
- src/Cryptol/TypeCheck/TCon.hs +1/−1
- src/Cryptol/TypeCheck/Type.hs +177/−14
- src/Cryptol/TypeCheck/TypeOf.hs +6/−1
- src/Cryptol/TypeCheck/TypePat.hs +7/−0
- src/Cryptol/Utils/Benchmark.hs +36/−0
- src/Cryptol/Utils/Fixity.hs +2/−2
- src/Cryptol/Utils/Ident.hs +145/−46
- src/Cryptol/Utils/PP.hs +64/−17
- src/Cryptol/Utils/Panic.hs +4/−1
- src/Cryptol/Utils/Patterns.hs +1/−0
- src/Cryptol/Utils/RecordMap.hs +7/−0
- src/Cryptol/Utils/Types.hs +10/−0
- src/Cryptol/Version.hs +4/−1
CHANGES.md view
@@ -1,3 +1,103 @@+# 3.0.0 -- 2023-06-26++## Language changes++* Cryptol now includes a redesigned module system that is significantly more+ expressive than in previous releases. The new module system includes the+ following features:++ * Nested modules: Modules may now be defined within other modules.++ * Named interfaces: An interface specifies the parameters to a module.+ Separating the interface from the parameter declarations makes it possible+ to have different parameters that use the same interface.++ * Top-level module constraints: These are useful to specify constraints+ between different module parameters (i.e., ones that come from different+ interfaces or multiple copies of the same interface).++ See the+ [manual section](https://galoisinc.github.io/cryptol/master/Modules.html#instantiation-by-parametrizing-declarations)+ for more information.++* Declarations may now use *numeric constraint guards*. This is a feature+ that allows a function to behave differently depending on its numeric+ type parameters. See the [manual section](https://galoisinc.github.io/cryptol/master/BasicSyntax.html#numeric-constraint-guards))+ for more information.++* The foreign function interface (FFI) has been added, which allows Cryptol to+ call functions written in C. See the [manual section](https://galoisinc.github.io/cryptol/master/FFI.html)+ for more information.++* The unary `-` operator now has the same precedence as binary `-`, meaning+ expressions like `-x^^2` will now parse as `-(x^^2)` instead of `(-x)^^2`.+ **This is a breaking change.** A warning has been added in cases where the+ behavior has changed, and can be disabled with `:set warnPrefixAssoc=off`.++* Infix operators are now allowed in import lists: `import M ((<+>))` will+ import only the operator `<+>` from module `M`.++* `lib/Array.cry` now contains an `arrayEq` primitive. Like the other+ array-related primitives, this has no computational interpretation (and+ therefore cannot be used in the Cryptol interpreter), but it is useful for+ stating specifications that are used in SAW.++## New features++* Add a `:time` command to benchmark the evaluation time of expressions.++* Add support for literate Cryptol using reStructuredText. Cryptol code+ is extracted from `.. code-block:: cryptol` and `.. sourcecode:: cryptol`+ directives.++* Add a syntax highlight file for Vim,+ available in `syntax-highlight/cryptol.vim`++* Add `:new-seed` and `:set-seed` commands to the REPL.+ These affect random test generation,+ and help write reproducable Cryptol scripts.++* Add support for the CVC5 solver, which can be selected with+ `:set prover=cvc5`. If you want to specify a What4 or SBV backend, you can+ use `:set prover=w4-cvc5` or `:set prover=sbv-cvc5`, respectively. (Note that+ `sbv-cvc5` is non-functional on Windows at this time due to a downstream issue+ with CVC5 1.0.4 and earlier.)++* Add `:file-deps` commands to the REPL and Python API.+ It shows information about the source files and dependencies of+ modules or Cryptol files.++## Bug fixes++* Fix a bug in the What4 backend that could cause applications of `(@)` with+ symbolic `Integer` indices to become out of bounds (#1359).++* Fix a bug that caused finite bitvector enumerations to panic when used in+ combination with `(#)` (e.g., `[0..1] # 0`).++* Cryptol's markdown parser is slightly more permissive and will now parse code+ blocks with whitespace in between the backticks and `cryptol`. This sort of+ whitespace is often inserted by markdown generation tools such as `pandoc`.++* Improve documentation for `fromInteger` (#1465)++* Closed issues #812, #977, #1090, #1140, #1147, #1253, #1322, #1324, #1329,+ #1344, #1347, #1351, #1354, #1355, #1359, #1366, #1368, #1370, #1371, #1372,+ #1373, #1378, #1383, #1385, #1386, #1391, #1394, #1395, #1396, #1398, #1399,+ #1404, #1415, #1423, #1435, #1439, #1440, #1441, #1442, #1444, #1445, #1448,+ #1449, #1450, #1451, #1452, #1456, #1457, #1458, #1462, #1465, #1466, #1470,+ #1475, #1480, #1483, #1484, #1485, #1487, #1488, #1491, #1496, #1497, #1501,+ #1503, #1510, #1511, #1513, and #1514.++* Merged pull requests #1184, #1205, #1279, #1356, #1357, #1358, #1361, #1363,+ #1365, #1367, #1376, #1379, #1380, #1384, #1387, #1388, #1393, #1401, #1402,+ #1403, #1406, #1408, #1409, #1410, #1411, #1412, #1413, #1414, #1416, #1417,+ #1418, #1419, #1420, #1422, #1424, #1429, #1430, #1431, #1432, #1436, #1438,+ #1443, #1447, #1453, #1454, #1459, #1460, #1461, #1463, #1464, #1467, #1468,+ #1472, #1473, #1474, #1476, #1477, #1478, #1481, #1493, #1499, #1502, #1504,+ #1506, #1509, #1512, #1516, #1518, #1519, #1520, #1521, #1523, #1527, and+ #1528.+ # 2.13.0 ## Language changes
bench/Main.hs view
@@ -26,7 +26,6 @@ import qualified Cryptol.ModuleSystem.Env as M import qualified Cryptol.ModuleSystem.Monad as M import qualified Cryptol.ModuleSystem.NamingEnv as M-import Cryptol.ModuleSystem.Interface (noIfaceParams) import qualified Cryptol.Parser as P import qualified Cryptol.Parser.AST as P@@ -130,7 +129,7 @@ , M.tcLinter = M.moduleLinter (P.thing (P.mName scm)) , M.tcPrims = prims }- M.typecheck act scm noIfaceParams tcEnv+ M.typecheck act scm mempty tcEnv ceval :: String -> String -> FilePath -> T.Text -> Benchmark ceval cd name path expr =
cryptol.cabal view
@@ -1,6 +1,6 @@ Cabal-version: 2.4 Name: cryptol-Version: 2.13.0+Version: 3.0.0 Synopsis: Cryptol: The Language of Cryptography Description: Cryptol is a domain-specific language for specifying cryptographic algorithms. A Cryptol implementation of an algorithm resembles its mathematical specification more closely than an implementation in a general purpose language. For more, see <http://www.cryptol.net/>. License: BSD-3-Clause@@ -9,11 +9,12 @@ Maintainer: cryptol@galois.com Homepage: http://www.cryptol.net/ Bug-reports: https://github.com/GaloisInc/cryptol/issues-Copyright: 2013-2021 Galois Inc.+Copyright: 2013-2022 Galois Inc. Category: Language Build-type: Simple extra-source-files: bench/data/*.cry CHANGES.md+ lib/*.cry lib/*.z3 data-files: **/*.cry **/*.z3 data-dir: lib@@ -26,7 +27,7 @@ type: git location: https://github.com/GaloisInc/cryptol.git -- add a tag on release branches- tag: 2.13.0+ tag: 3.0.0 flag static@@ -37,6 +38,10 @@ default: True description: Don't use the Cabal-provided data directory for looking up Cryptol libraries. This is useful when the data directory can't be known ahead of time, like for a relocatable distribution. +flag ffi+ default: True+ description: Enable the foreign function interface+ library Default-language: Haskell2010@@ -48,6 +53,7 @@ bytestring >= 0.10, array >= 0.4, containers >= 0.5,+ criterion-measurement, cryptohash-sha1 >= 0.11 && < 0.12, deepseq >= 1.3, directory >= 1.2.2.0,@@ -57,30 +63,44 @@ ghc-prim, GraphSCC >= 1.0.4, heredoc >= 0.2,+ language-c99,+ language-c99-simple, libBF >= 0.6 && < 0.7, MemoTrie >= 0.6 && < 0.7, monad-control >= 1.0, monadLib >= 3.7.2, parameterized-utils >= 2.0.2,+ pretty, prettyprinter >= 1.7.0,+ pretty-show, process >= 1.2,- sbv >= 8.10 && < 9.1,+ sbv >= 9.1 && < 10.2, simple-smt >= 0.9.7, stm >= 2.4, strict, text >= 1.1, tf-random >= 0.5, transformers-base >= 0.4,+ vector, mtl >= 2.2.1, time >= 1.6.0.1, panic >= 0.3,- what4 >= 1.3 && < 1.4+ what4 >= 1.4 && < 1.5 if impl(ghc >= 9.0)- build-depends: ghc-bignum >= 1.0 && < 1.3+ build-depends: ghc-bignum >= 1.0 && < 1.4 else build-depends: integer-gmp >= 1.0 && < 1.1 + if flag(ffi)+ build-depends: hgmp,+ libffi >= 0.2+ if os(windows)+ build-depends: Win32+ else+ build-depends: unix+ cpp-options: -DFFI_ENABLED+ Build-tool-depends: alex:alex, happy:happy hs-source-dirs: src @@ -93,6 +113,7 @@ Cryptol.Parser.Names, Cryptol.Parser.Name, Cryptol.Parser.NoPat,+ Cryptol.Parser.ExpandPropGuards, Cryptol.Parser.NoInclude, Cryptol.Parser.Selector, Cryptol.Parser.Utils,@@ -107,6 +128,8 @@ Cryptol.Utils.Misc, Cryptol.Utils.Patterns, Cryptol.Utils.Logger,+ Cryptol.Utils.Benchmark,+ Cryptol.Utils.Types, Cryptol.Version, Cryptol.ModuleSystem,@@ -116,10 +139,13 @@ Cryptol.ModuleSystem.Interface, Cryptol.ModuleSystem.Monad, Cryptol.ModuleSystem.Name,+ Cryptol.ModuleSystem.Names, Cryptol.ModuleSystem.NamingEnv,+ Cryptol.ModuleSystem.Binds Cryptol.ModuleSystem.Exports,- Cryptol.ModuleSystem.InstantiateModule, Cryptol.ModuleSystem.Renamer,+ Cryptol.ModuleSystem.Renamer.Imports,+ Cryptol.ModuleSystem.Renamer.ImplicitImports, Cryptol.ModuleSystem.Renamer.Monad, Cryptol.ModuleSystem.Renamer.Error, @@ -132,7 +158,6 @@ Cryptol.TypeCheck.Parseable, Cryptol.TypeCheck.Monad, Cryptol.TypeCheck.Infer,- Cryptol.TypeCheck.CheckModuleInstance, Cryptol.TypeCheck.InferTypes, Cryptol.TypeCheck.Interface, Cryptol.TypeCheck.Error,@@ -147,6 +172,12 @@ Cryptol.TypeCheck.TypeMap, Cryptol.TypeCheck.TypeOf, Cryptol.TypeCheck.Sanity,+ Cryptol.TypeCheck.FFI,+ Cryptol.TypeCheck.FFI.Error,+ Cryptol.TypeCheck.FFI.FFIType,+ Cryptol.TypeCheck.Module,+ Cryptol.TypeCheck.ModuleInstance,+ Cryptol.TypeCheck.ModuleBacktickInstance, Cryptol.TypeCheck.Solver.Types, Cryptol.TypeCheck.Solver.SMT,@@ -162,13 +193,15 @@ Cryptol.Transform.MonoValues, Cryptol.Transform.Specialize,- Cryptol.Transform.AddModParams, Cryptol.IR.FreeVars,+ Cryptol.IR.TraverseNames, Cryptol.Backend, Cryptol.Backend.Arch, Cryptol.Backend.Concrete,+ Cryptol.Backend.FFI,+ Cryptol.Backend.FFI.Error, Cryptol.Backend.FloatHelpers, Cryptol.Backend.Monad, Cryptol.Backend.SeqMap,@@ -179,6 +212,8 @@ Cryptol.Eval, Cryptol.Eval.Concrete, Cryptol.Eval.Env,+ Cryptol.Eval.FFI,+ Cryptol.Eval.FFI.GenHeader, Cryptol.Eval.Generic, Cryptol.Eval.Prims, Cryptol.Eval.Reference,@@ -199,6 +234,7 @@ Cryptol.Symbolic.What4, Cryptol.REPL.Command,+ Cryptol.REPL.Help, Cryptol.REPL.Browse, Cryptol.REPL.Monad, Cryptol.REPL.Trie
cryptol/CheckExercises.hs view
@@ -291,7 +291,7 @@ if Seq.null (rdReplout rd) then do let cryCmd = (P.shell (exe ++ " --interactive-batch " ++ inFile ++ " -e"))- (cryEC, cryOut, _) <- P.readCreateProcessWithExitCode cryCmd ""+ (cryEC, cryOut, cryErr) <- P.readCreateProcessWithExitCode cryCmd "" Line lnReplinStart _ Seq.:<| _ <- return $ rdReplin rd@@ -301,6 +301,7 @@ putStrLn $ "REPL error (replin lines " ++ show lnReplinStart ++ "-" ++ show lnReplinEnd ++ ")." putStr cryOut+ putStr cryErr exitFailure ExitSuccess -> do -- remove temporary input file
cryptol/Main.hs view
@@ -200,7 +200,7 @@ , "via the `:edit` command" ] )- , ( "SBV_{ABC,BOOLECTOR,CVC4,MATHSAT,YICES,Z3}_OPTIONS"+ , ( "SBV_{ABC,BOOLECTOR,CVC4,CVC5,MATHSAT,YICES,Z3}_OPTIONS" , [ "A string of command-line arguments to be passed to the" , "corresponding solver invoked for `:sat` and `:prove`" , "when using a prover via SBV"
lib/Array.cry view
@@ -10,6 +10,7 @@ primitive arrayConstant : {a, b} b -> (Array a b) primitive arrayLookup : {a, b} (Array a b) -> a -> b primitive arrayUpdate : {a, b} (Array a b) -> a -> b -> (Array a b)+primitive arrayEq : {n, a} (Array [n] a) -> (Array [n] a) -> Bool /** * Copy elements from the source array to the destination array.
lib/Cryptol.cry view
@@ -339,11 +339,21 @@ primitive type Ring : * -> Prop /**- * Converts an unbounded integer to a value in a Ring. When converting- * to the bitvector type [n], the value is reduced modulo 2^^n. Likewise,- * when converting to Z n, the value is reduced modulo n. When converting- * to a floating-point value, the value is rounded to the nearest- * representable value.+ * Converts an unbounded integer to a value in a Ring using the following rules:+ * * to bitvector type [n]:+ * the value is reduced modulo 2^^n,+ * * to Z n:+ * the value is reduced modulo n,+ * * floating point types:+ * the value is rounded to the nearest representable value,+ * * sequences other than bitvectors:+ * elements are computed by using `fromInteger` pointwise+ * Example: (fromInteger 2 : [3][8]) === [ 0x02, 0x02, 0x02 ]+ * * tuples and records:+ * elements are computed by using `fromInteger` pointwise+ * Example: (fromInteger 2 : (Integer,[3][8])) === (2, [ 0x2, 0x2, 0x2 ])+ * * functions:+ * a constant function returning `fromInteger` on the result type */ primitive fromInteger : {a} (Ring a) => Integer -> a
+ src/Cryptol/Backend/FFI.hs view
@@ -0,0 +1,276 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- | The implementation of loading and calling external functions from shared+-- libraries.+module Cryptol.Backend.FFI+ ( ForeignSrc+ , getForeignSrcPath+ , loadForeignSrc+ , unloadForeignSrc+ , foreignLibPath+#ifdef FFI_ENABLED+ , ForeignImpl+ , loadForeignImpl+ , FFIArg+ , FFIRet+ , SomeFFIArg (..)+ , callForeignImpl+#endif+ )+ where++import Control.DeepSeq++import Cryptol.Backend.FFI.Error++#ifdef FFI_ENABLED++import Control.Concurrent.MVar+import Control.Exception+import Control.Monad+import Data.Bifunctor+import Data.Word+import Foreign hiding (newForeignPtr)+import Foreign.C.Types+import Foreign.Concurrent+import Foreign.LibFFI+import System.FilePath ((-<.>))+import System.Directory(doesFileExist)+import System.IO.Error+import System.Info(os)++#if defined(mingw32_HOST_OS)+import System.Win32.DLL+#else+import System.Posix.DynamicLinker+#endif++import Cryptol.Utils.Panic++#else++import GHC.Generics++#endif++#ifdef FFI_ENABLED++-- | A source from which we can retrieve implementations of foreign functions.+data ForeignSrc = ForeignSrc+ { -- | The file path of the 'ForeignSrc'.+ foreignSrcPath :: FilePath+ -- | The 'ForeignPtr' wraps the pointer returned by 'dlopen', where the+ -- finalizer calls 'dlclose' when the library is no longer needed. We keep+ -- references to the 'ForeignPtr' in each foreign function that is in the+ -- evaluation environment, so that the shared library will stay open as long+ -- as there are references to it.+ , foreignSrcFPtr :: ForeignPtr ()+ -- | We support explicit unloading of the shared library so we keep track of+ -- if it has already been unloaded, and if so the finalizer does nothing.+ -- This is updated atomically when the library is unloaded.+ , foreignSrcLoaded :: MVar Bool }++instance Show ForeignSrc where+ show = show . foreignSrcFPtr++instance NFData ForeignSrc where+ rnf ForeignSrc {..} = foreignSrcFPtr `seq` foreignSrcLoaded `deepseq` ()++-- | Get the file path of the 'ForeignSrc'.+getForeignSrcPath :: ForeignSrc -> Maybe FilePath+getForeignSrcPath = Just . foreignSrcPath++-- | Load a 'ForeignSrc' for the given __Cryptol__ file path. The file path of+-- the shared library that we try to load is the same as the Cryptol file path+-- except with a platform specific extension.+loadForeignSrc :: FilePath -> IO (Either FFILoadError ForeignSrc)+loadForeignSrc = loadForeignLib >=> traverse \(foreignSrcPath, ptr) -> do+ foreignSrcLoaded <- newMVar True+ foreignSrcFPtr <- newForeignPtr ptr (unloadForeignSrc' foreignSrcLoaded ptr)+ pure ForeignSrc {..}+++-- | Given the path to a Cryptol module, compute the location of+-- the shared library we'd like to load.+foreignLibPath :: FilePath -> IO (Maybe FilePath)+foreignLibPath path =+ search+ case os of+ "mingw32" -> ["dll"]+ "darwin" -> ["dylib","so"]+ _ -> ["so"]++ where+ search es =+ case es of+ [] -> pure Nothing+ e : more ->+ do let p = path -<.> e+ yes <- doesFileExist p+ if yes then pure (Just p) else search more+++loadForeignLib :: FilePath -> IO (Either FFILoadError (FilePath, Ptr ()))+loadForeignLib path =+ do mb <- foreignLibPath path+ case mb of+ Nothing -> pure (Left (CantLoadFFISrc path "File not found"))+ Just libPath -> tryLoad (CantLoadFFISrc path) (open libPath)++ where open libPath = do+#if defined(mingw32_HOST_OS)+ ptr <- loadLibrary libPath+#else+ -- RTLD_NOW so we can make sure that the symbols actually exist at+ -- module loading time+ ptr <- undl <$> dlopen libPath [RTLD_NOW]+#endif+ pure (libPath, ptr)++-- | Explicitly unload a 'ForeignSrc' immediately instead of waiting for the+-- garbage collector to do it. This can be useful if you want to immediately+-- load the same library again to pick up new changes.+--+-- The 'ForeignSrc' __must not__ be used in any way after this is called,+-- including calling 'ForeignImpl's loaded from it.+unloadForeignSrc :: ForeignSrc -> IO ()+unloadForeignSrc ForeignSrc {..} = withForeignPtr foreignSrcFPtr $+ unloadForeignSrc' foreignSrcLoaded++unloadForeignSrc' :: MVar Bool -> Ptr () -> IO ()+unloadForeignSrc' loaded lib = modifyMVar_ loaded \l -> do+ when l $ unloadForeignLib lib+ pure False++unloadForeignLib :: Ptr () -> IO ()+#if defined(mingw32_HOST_OS)+unloadForeignLib = freeLibrary+#else+unloadForeignLib = dlclose . DLHandle+#endif++withForeignSrc :: ForeignSrc -> (Ptr () -> IO a) -> IO a+withForeignSrc ForeignSrc {..} f = withMVar foreignSrcLoaded+ \case+ True -> withForeignPtr foreignSrcFPtr f+ False ->+ panic "[FFI] withForeignSrc" ["Use of foreign library after unload"]++-- | An implementation of a foreign function.+data ForeignImpl = ForeignImpl+ { foreignImplFun :: FunPtr ()+ -- | We don't need this to call the function but we want to keep the library+ -- around as long as we still have a function from it so that it isn't+ -- unloaded too early.+ , foreignImplSrc :: ForeignSrc+ }++-- | Load a 'ForeignImpl' with the given name from the given 'ForeignSrc'.+loadForeignImpl :: ForeignSrc -> String -> IO (Either FFILoadError ForeignImpl)+loadForeignImpl foreignImplSrc name =+ withForeignSrc foreignImplSrc \lib ->+ tryLoad (CantLoadFFIImpl name) do+ foreignImplFun <- loadForeignFunPtr lib name+ pure ForeignImpl {..}++loadForeignFunPtr :: Ptr () -> String -> IO (FunPtr ())+#if defined(mingw32_HOST_OS)+loadForeignFunPtr source symbol = do+ addr <- getProcAddress source symbol+ pure $ castPtrToFunPtr addr+#else+loadForeignFunPtr = dlsym . DLHandle+#endif++tryLoad :: (String -> FFILoadError) -> IO a -> IO (Either FFILoadError a)+tryLoad err = fmap (first $ err . displayException) . tryIOError++-- | Types which can be converted into libffi arguments.+--+-- The Storable constraint is so that we can put them in arrays.+class Storable a => FFIArg a where+ ffiArg :: a -> Arg++instance FFIArg Word8 where+ ffiArg = argWord8++instance FFIArg Word16 where+ ffiArg = argWord16++instance FFIArg Word32 where+ ffiArg = argWord32++instance FFIArg Word64 where+ ffiArg = argWord64++instance FFIArg CFloat where+ ffiArg = argCFloat++instance FFIArg CDouble where+ ffiArg = argCDouble++instance FFIArg (Ptr a) where+ ffiArg = argPtr++instance FFIArg CSize where+ ffiArg = argCSize++-- | Types which can be returned from libffi.+--+-- The Storable constraint is so that we can put them in arrays.+class Storable a => FFIRet a where+ ffiRet :: RetType a++instance FFIRet Word8 where+ ffiRet = retWord8++instance FFIRet Word16 where+ ffiRet = retWord16++instance FFIRet Word32 where+ ffiRet = retWord32++instance FFIRet Word64 where+ ffiRet = retWord64++instance FFIRet CFloat where+ ffiRet = retCFloat++instance FFIRet CDouble where+ ffiRet = retCDouble++instance FFIRet () where+ ffiRet = retVoid++-- | Existential wrapper around a 'FFIArg'.+data SomeFFIArg = forall a. FFIArg a => SomeFFIArg a++-- | Call a 'ForeignImpl' with the given arguments. The type parameter decides+-- how the return value should be converted into a Haskell value.+callForeignImpl :: forall a. FFIRet a => ForeignImpl -> [SomeFFIArg] -> IO a+callForeignImpl ForeignImpl {..} xs = withForeignSrc foreignImplSrc \_ ->+ callFFI foreignImplFun (ffiRet @a) $ map toArg xs+ where toArg (SomeFFIArg x) = ffiArg x++#else++data ForeignSrc = ForeignSrc deriving (Show, Generic, NFData)++getForeignSrcPath :: ForeignSrc -> Maybe FilePath+getForeignSrcPath _ = Nothing++loadForeignSrc :: FilePath -> IO (Either FFILoadError ForeignSrc)+loadForeignSrc _ = pure $ Right ForeignSrc++unloadForeignSrc :: ForeignSrc -> IO ()+unloadForeignSrc _ = pure ()++#endif
+ src/Cryptol/Backend/FFI/Error.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Safe #-}++-- | Errors from dynamic loading of shared libraries for FFI.+module Cryptol.Backend.FFI.Error where++import Control.DeepSeq+import GHC.Generics++import Cryptol.Utils.PP+import Cryptol.ModuleSystem.Name++data FFILoadError+ = CantLoadFFISrc+ FilePath -- ^ Path to cryptol module+ String -- ^ Error message+ | CantLoadFFIImpl+ String -- ^ Function name+ String -- ^ Error message+ | FFIDuplicates [Name]+ | FFIInFunctor Name+ deriving (Show, Generic, NFData)++instance PP FFILoadError where+ ppPrec _ e =+ case e of+ CantLoadFFISrc path msg ->+ hang ("Could not load foreign source for module located at"+ <+> text path <.> colon)+ 4 (text msg)+ CantLoadFFIImpl name msg ->+ hang ("Could not load foreign implementation for binding"+ <+> text name <.> colon)+ 4 (text msg)+ FFIDuplicates xs ->+ hang "Multiple foreign declarations with the same name:"+ 4 (backticks (pp (nameIdent (head xs))) <+>+ "defined at" <+> align (vcat (map (pp . nameLoc) xs)))+ FFIInFunctor x ->+ hang (pp (nameLoc x) <.> ":")+ 4 "Foreign declaration" <+> backticks (pp (nameIdent x)) <+>+ "may not appear in a parameterized module."
src/Cryptol/Backend/FloatHelpers.hs view
@@ -8,6 +8,7 @@ import Cryptol.Utils.PP import Cryptol.Utils.Panic(panic)+import Cryptol.Utils.Types import Cryptol.Backend.Monad( EvalError(..) ) @@ -176,3 +177,8 @@ -- (most significant bit in the significand is set, the rest of it is 0) floatToBits :: Integer -> Integer -> BigFloat -> Integer floatToBits e p bf = bfToBits (fpOpts e p NearEven) bf+++-- | Create a 64-bit IEEE-754 float.+floatFromDouble :: Double -> BF+floatFromDouble = uncurry BF float64ExpPrec . bfFromDouble
src/Cryptol/Backend/Monad.hs view
@@ -54,7 +54,7 @@ import Cryptol.Parser.Position import Cryptol.Utils.Panic import Cryptol.Utils.PP-import Cryptol.TypeCheck.AST(Name)+import Cryptol.TypeCheck.AST(Name, TParam) -- | A computation that returns an already-evaluated value. ready :: a -> Eval a@@ -412,16 +412,20 @@ -- | Data type describing errors that can occur during evaluation. data EvalError- = InvalidIndex (Maybe Integer) -- ^ Out-of-bounds index- | DivideByZero -- ^ Division or modulus by 0- | NegativeExponent -- ^ Exponentiation by negative integer- | LogNegative -- ^ Logarithm of a negative integer- | UserError String -- ^ Call to the Cryptol @error@ primitive- | LoopError String -- ^ Detectable nontermination- | NoPrim Name -- ^ Primitive with no implementation- | BadRoundingMode Integer -- ^ Invalid rounding mode- | BadValue String -- ^ Value outside the domain of a partial function.- deriving Typeable+ = InvalidIndex (Maybe Integer) -- ^ Out-of-bounds index+ | DivideByZero -- ^ Division or modulus by 0+ | NegativeExponent -- ^ Exponentiation by negative integer+ | LogNegative -- ^ Logarithm of a negative integer+ | UserError String -- ^ Call to the Cryptol @error@ primitive+ | LoopError String -- ^ Detectable nontermination+ | NoPrim Name -- ^ Primitive with no implementation+ | BadRoundingMode Integer -- ^ Invalid rounding mode+ | BadValue String -- ^ Value outside the domain of a partial function.+ | NoMatchingPropGuardCase String -- ^ No prop guard holds for the given type variables.+ | FFINotSupported Name -- ^ Foreign function cannot be called+ | FFITypeNumTooBig Name TParam Integer -- ^ Number passed to foreign function+ -- as a type argument is too large+ deriving Typeable instance PP EvalError where ppPrec _ e = case e of@@ -440,6 +444,18 @@ BadRoundingMode r -> "invalid rounding mode" <+> integer r BadValue x -> "invalid input for" <+> backticks (text x) NoPrim x -> text "unimplemented primitive:" <+> pp x+ NoMatchingPropGuardCase msg -> text $ "No matching constraint guard; " ++ msg+ FFINotSupported x -> vcat+ [ text "cannot call foreign function" <+> pp x+ , text "FFI calls are not supported in this context"+ , text "If you are trying to evaluate an expression, try rebuilding"+ , text " Cryptol with FFI support enabled."+ ]+ FFITypeNumTooBig f p n -> vcat+ [ text "numeric type argument to foreign function is too large:"+ <+> integer n+ , text "in type parameter" <+> pp p <+> "of function" <+> pp f+ , text "type arguments must fit in a C `size_t`" ] instance Show EvalError where show = show . pp
src/Cryptol/Backend/What4.hs view
@@ -11,6 +11,7 @@ {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE ViewPatterns #-} module Cryptol.Backend.What4 where
src/Cryptol/Eval.hs view
@@ -15,6 +15,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE NamedFieldPuns #-} module Cryptol.Eval ( moduleEnv@@ -35,6 +36,7 @@ , Unsupported(..) , WordTooWide(..) , forceValue+ , checkProp ) where import Cryptol.Backend@@ -63,6 +65,7 @@ import qualified Data.IntMap.Strict as IntMap import qualified Data.Map.Strict as Map import Data.Semigroup+import Control.Applicative import Prelude () import Prelude.Compat@@ -171,8 +174,9 @@ Just (Right val) | ?callStacks -> case nameInfo n of- Declared{} -> sPushFrame sym n ?range (cacheCallStack sym =<< val)- Parameter -> cacheCallStack sym =<< val+ GlobalName {} ->+ sPushFrame sym n ?range (cacheCallStack sym =<< val)+ LocalName {} -> cacheCallStack sym =<< val | otherwise -> val Nothing -> do envdoc <- ppEnv sym defaultPPOpts env@@ -215,13 +219,59 @@ env' <- evalDecls sym ds env evalExpr sym env' e + EPropGuards guards _ -> {-# SCC "evalExpr->EPropGuards" #-} do+ let checkedGuards = [ e | (ps,e) <- guards, all (checkProp . evalProp env) ps ]+ case checkedGuards of+ (e:_) -> eval e+ [] -> raiseError sym (NoMatchingPropGuardCase $ "Among constraint guards: " ++ show (fmap pp . fst <$> guards))+ where {-# INLINE eval #-} eval = evalExpr sym env ppV = ppValue sym defaultPPOpts +-- | Checks whether an evaluated `Prop` holds+checkProp :: Prop -> Bool+checkProp = \case+ TCon tcon ts ->+ let ns = toNat' <$> ts in+ case tcon of+ PC PEqual | [n1, n2] <- ns -> n1 == n2+ PC PNeq | [n1, n2] <- ns -> n1 /= n2+ PC PGeq | [n1, n2] <- ns -> n1 >= n2+ PC PFin | [n] <- ns -> n /= Inf+ -- TODO: instantiate UniqueFactorization for Nat'?+ -- PC PPrime | [n] <- ns -> isJust (isPrime n) + PC PTrue -> True+ TError {} -> False+ _ -> evalPanic "evalProp" ["cannot use this as a guarding constraint: ", show . pp $ TCon tcon ts ]+ prop -> evalPanic "evalProp" ["cannot use this as a guarding constraint: ", show . pp $ prop ]+ where+ toNat' :: Type -> Nat'+ toNat' = \case+ TCon (TC (TCNum n)) [] -> Nat n+ TCon (TC TCInf) [] -> Inf+ prop -> panic "checkProp" ["Expected `" ++ pretty prop ++ "` to be an evaluated numeric type"] ++-- | Evaluates a `Prop` in an `EvalEnv` by substituting all variables according+-- to `envTypes` and expanding all type synonyms via `tNoUser`.+evalProp :: GenEvalEnv sym -> Prop -> Prop+evalProp env@EvalEnv { envTypes } = \case+ TCon tc tys+ | TError KProp <- tc, [p] <- tys ->+ case evalProp env p of+ x@(TCon (TError KProp) _) -> x+ _ -> TCon (TError KProp) [evalProp env p]+ | otherwise -> TCon tc (toType . evalType envTypes <$> tys)+ TVar tv | Just (toType -> ty) <- lookupTypeVar tv envTypes -> ty+ prop@TUser {} -> evalProp env (tNoUser prop)+ TVar tv | Nothing <- lookupTypeVar tv envTypes -> panic "evalProp" ["Could not find type variable `" ++ pretty tv ++ "` in the type evaluation environment"]+ prop -> panic "evalProp" ["Cannot use the following as a type constraint: `" ++ pretty prop ++ "`"]+ where+ toType = either tNumTy tValTy+ -- | Capure the current call stack from the evaluation monad and -- annotate function values. When arguments are later applied -- to the function, the call stacks will be combined together.@@ -269,7 +319,7 @@ Newtype -> GenEvalEnv sym -> SEval sym (GenEvalEnv sym)-evalNewtypeDecl _sym nt = pure . bindVarDirect (ntName nt) (foldr tabs con (ntParams nt))+evalNewtypeDecl _sym nt = pure . bindVarDirect (ntConName nt) (foldr tabs con (ntParams nt)) where con = PFun PPrim @@ -382,9 +432,11 @@ sym -> Decl -> SEval sym (Name, Schema, SEval sym (GenValue sym), SEval sym (GenValue sym) -> SEval sym ()) declHole sym d = case dDefinition d of- DPrim -> evalPanic "Unexpected primitive declaration in recursive group"- [show (ppLocName nm)]- DExpr _ -> do+ DPrim -> evalPanic "Unexpected primitive declaration in recursive group"+ [show (ppLocName nm)]+ DForeign _ -> evalPanic "Unexpected foreign declaration in recursive group"+ [show (ppLocName nm)]+ DExpr _ -> do (hole, fill) <- sDeclareHole sym msg return (nm, sch, hole, fill) where@@ -407,8 +459,10 @@ GenEvalEnv sym {- ^ An evaluation environment to extend with the given declaration -} -> Decl {- ^ The declaration to evaluate -} -> SEval sym (GenEvalEnv sym)-evalDecl sym renv env d =- let ?range = nameLoc (dName d) in+-- evalDecl sym renv env d =+-- let ?range = nameLoc (dName d) in+evalDecl sym renv env d = do+ let ?range = nameLoc (dName d) case dDefinition d of DPrim -> case ?evalPrim =<< asPrim (dName d) of@@ -416,6 +470,18 @@ Just (Left ex) -> bindVar sym (dName d) (evalExpr sym renv ex) env Nothing -> bindVar sym (dName d) (cryNoPrimError sym (dName d)) env + DForeign _ -> do+ -- Foreign declarations should have been handled by the previous+ -- Cryptol.Eval.FFI.evalForeignDecls pass already, so they should already+ -- be in the environment. If not, then either Cryptol was not compiled+ -- with FFI support enabled, or we are in a non-Concrete backend. In that+ -- case, we just bind the name to an error computation which will raise an+ -- error if we try to evaluate it.+ case lookupVar (dName d) env of+ Just _ -> pure env+ Nothing -> bindVar sym (dName d)+ (raiseError sym $ FFINotSupported $ dName d) env+ DExpr e -> bindVar sym (dName d) (evalExpr sym renv e) env @@ -689,5 +755,6 @@ where f env = case dDefinition d of- DPrim -> evalPanic "evalMatch" ["Unexpected local primitive"]- DExpr e -> evalExpr sym env e+ DPrim -> evalPanic "evalMatch" ["Unexpected local primitive"]+ DForeign _ -> evalPanic "evalMatch" ["Unexpected local foreign"]+ DExpr e -> evalExpr sym env e
src/Cryptol/Eval/Concrete.hs view
@@ -8,16 +8,10 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE BlockArguments #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternGuards #-} {-# LANGUAGE Rank2Types #-}-{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ViewPatterns #-} module Cryptol.Eval.Concrete ( module Cryptol.Backend.Concrete , Value@@ -87,7 +81,7 @@ case res of Left _ -> mismatch -- different fields Right efs ->- let f = foldl (\x t -> ETApp x (tNumValTy t)) (EVar (ntName nt)) ts+ let f = foldl (\x t -> ETApp x (tNumValTy t)) (EVar (ntConName nt)) ts in pure (EApp f (ERec efs)) (TVTuple ts, VTuple tvs) ->
+ src/Cryptol/Eval/FFI.hs view
@@ -0,0 +1,430 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}++-- | Evaluation of foreign functions.+module Cryptol.Eval.FFI+ ( findForeignDecls+ , evalForeignDecls+ ) where++import Cryptol.Backend.FFI+import Cryptol.Backend.FFI.Error+import Cryptol.Eval+import Cryptol.TypeCheck.AST+import Cryptol.TypeCheck.FFI.FFIType++#ifdef FFI_ENABLED++import Control.Exception(bracket_)+import Data.Either+import Data.Foldable+import Data.IORef+import Data.Proxy+import Data.Ratio+import Data.Traversable+import Data.Word+import Foreign+import Foreign.C.Types+import GHC.Float+import LibBF (bfFromDouble, bfToDouble,+ pattern NearEven)+import Numeric.GMP.Raw.Unsafe+import Numeric.GMP.Utils++import Cryptol.Backend+import Cryptol.Backend.Concrete+import Cryptol.Backend.FloatHelpers+import Cryptol.Backend.Monad+import Cryptol.Backend.SeqMap+import Cryptol.Eval.Env+import Cryptol.Eval.Prims+import Cryptol.Eval.Type+import Cryptol.Eval.Value+import Cryptol.ModuleSystem.Name+import Cryptol.Utils.Ident+import Cryptol.Utils.RecordMap++#endif++#ifdef FFI_ENABLED++-- | Add the given foreign declarations to the environment, loading their+-- implementations from the given 'ForeignSrc'. This is a separate pass from the+-- main evaluation functions in "Cryptol.Eval" since it only works for the+-- Concrete backend.+evalForeignDecls :: ForeignSrc -> [(Name, FFIFunType)] -> EvalEnv ->+ Eval (Either [FFILoadError] EvalEnv)+evalForeignDecls fsrc decls env = io do+ ePrims <- for decls \(name, ffiFunType) ->+ fmap ((name,) . foreignPrimPoly name ffiFunType) <$>+ loadForeignImpl fsrc (unpackIdent $ nameIdent name)+ pure case partitionEithers ePrims of+ ([], prims) -> Right $ foldr (uncurry bindVarDirect) env prims+ (errs, _) -> Left errs++-- | Generate a 'Prim' value representing the given foreign function, containing+-- all the code necessary to marshal arguments and return values and do the+-- actual FFI call.+foreignPrimPoly :: Name -> FFIFunType -> ForeignImpl -> Prim Concrete+foreignPrimPoly name fft impl = buildNumPoly (ffiTParams fft) mempty+ where -- Add type lambdas for the type parameters and build a type environment+ -- that we can look up later to compute e.g. array sizes.+ --+ -- Given [p1, p2, ..., pk] {}, returns+ -- PNumPoly \n1 -> PNumPoly \n2 -> ... PNumPoly \nk ->+ -- foreignPrim name fft impl {p1 = n1, p2 = n2, ..., pk = nk}+ buildNumPoly (tp:tps) tenv = PNumPoly \n ->+ buildNumPoly tps $ bindTypeVar (TVBound tp) (Left n) tenv+ buildNumPoly [] tenv = foreignPrim name fft impl tenv++-- | Methods for obtaining a return value. The producer of this type must supply+-- both 1) a polymorphic IO object directly containing a return value that the+-- consumer can instantiate at any 'FFIRet' type, and 2) an effectful function+-- that takes some output arguments and modifies what they are pointing at to+-- store a return value. The consumer can choose which one to use.+data GetRet = GetRet+ { getRetAsValue :: forall a. FFIRet a => IO a+ , getRetAsOutArgs :: [SomeFFIArg] -> IO () }++-- | Operations needed for returning a basic reference type.+data BasicRefRet a = BasicRefRet+ { -- | Initialize the object before passing to foreign function.+ initBasicRefRet :: Ptr a -> IO ()+ -- | Free the object after returning from foreign function and obtaining+ -- return value.+ , clearBasicRefRet :: Ptr a -> IO ()+ -- | Convert the object to a Cryptol value.+ , marshalBasicRefRet :: a -> Eval (GenValue Concrete) }++-- | Generate the monomorphic part of the foreign 'Prim', given a 'TypeEnv'+-- containing all the type arguments we have already received.+foreignPrim :: Name -> FFIFunType -> ForeignImpl -> TypeEnv -> Prim Concrete+foreignPrim name FFIFunType {..} impl tenv = buildFun ffiArgTypes []+ where++ -- Build up the 'Prim' function for the FFI call.+ --+ -- Given [t1, t2 ... tm] we return+ -- PStrict \v1 -> PStrict \v2 -> ... PStrict \vm -> PPrim $+ -- marshalArg t1 v1 \a1 ->+ -- marshalArg t2 v2 \a2 -> ... marshalArg tm vm \am ->+ -- marshalRet ffiRetType GetRet+ -- { getRetAsValue = callForeignImpl impl [n1, ..., nk, a1, ..., am]+ -- , getRetAsOutArgs = \[o1, ..., ol] ->+ -- callForeignImpl impl [n1, ..., nk, a1, ..., am, o1, ..., ol] }+ buildFun :: [FFIType] -> [(FFIType, GenValue Concrete)] -> Prim Concrete+ buildFun (argType:argTypes) typesAndVals = PStrict \val ->+ buildFun argTypes $ typesAndVals ++ [(argType, val)]+ buildFun [] typesAndVals = PPrim $+ marshalArgs typesAndVals \inArgs -> do+ tyArgs <- traverse marshalTyArg ffiTParams+ let tyInArgs = tyArgs ++ inArgs+ marshalRet ffiRetType GetRet+ { getRetAsValue = callForeignImpl impl tyInArgs+ , getRetAsOutArgs = callForeignImpl impl . (tyInArgs ++) }++ -- Look up the value of a type parameter in the type environment and marshal+ -- it.+ marshalTyArg :: TParam -> Eval SomeFFIArg+ marshalTyArg tp+ | n <= toInteger (maxBound :: CSize) =+ pure $ SomeFFIArg @CSize $ fromInteger n+ | otherwise = raiseError Concrete $ FFITypeNumTooBig name tp n+ where n = evalFinType $ TVar $ TVBound tp++ -- Marshal the given value as the given FFIType and call the given function+ -- with the results. A single Cryptol argument may correspond to any number of+ -- C arguments, so the callback takes a list.+ --+ -- NOTE: the result must be used only in the callback since it may have a+ -- limited lifetime (e.g. pointer returned by alloca).+ marshalArg ::+ FFIType ->+ GenValue Concrete ->+ ([SomeFFIArg] -> Eval a) ->+ Eval a++ marshalArg FFIBool val f = f [SomeFFIArg @Word8 (fromBool (fromVBit val))]++ marshalArg (FFIBasic (FFIBasicVal t)) val f =+ getMarshalBasicValArg t \doExport ->+ do arg <- doExport val+ f [SomeFFIArg arg]++ marshalArg (FFIBasic (FFIBasicRef t)) val f =+ getMarshalBasicRefArg t \doExport ->+ -- Since we need to do Eval actions in an IO callback, we need to manually+ -- unwrap and wrap the Eval datatype+ Eval \stk ->+ doExport val \arg ->+ with arg \ptr ->+ runEval stk (f [SomeFFIArg ptr])++ marshalArg (FFIArray (map evalFinType -> sizes) bt) val f =+ case bt of++ FFIBasicVal t ->+ getMarshalBasicValArg t \doExport ->+ -- Since we need to do Eval actions in an IO callback,+ -- we need to manually unwrap and wrap the Eval datatype+ Eval \stk ->+ marshalArrayArg stk \v k ->+ k =<< runEval stk (doExport v)++ FFIBasicRef t -> Eval \stk ->+ getMarshalBasicRefArg t \doExport ->+ marshalArrayArg stk doExport++ where marshalArrayArg stk doExport =+ allocaArray (fromInteger (product sizes)) \ptr -> do+ -- Traverse the nested sequences and write the elements to the+ -- array in order.+ -- ns is the dimensions of the values we are currently+ -- processing.+ -- vs is the values we are currently processing.+ -- nvss is the stack of previous ns and vs that we keep track of+ -- that we push onto when we start processing a nested sequence+ -- and pop off when we finish processing the current ones.+ -- i is the index into the array.++ let+ -- write next element of multi-dimensional array+ write (n:ns) (v:vs) nvss !i =+ do vs' <- traverse (runEval stk)+ (enumerateSeqMap n (fromVSeq v))+ write ns vs' ((n, vs):nvss) i++ -- write next element in flat array+ write [] (v:vs) nvss !i =+ doExport v \rep ->+ do pokeElemOff ptr i rep+ write [] vs nvss (i + 1)++ -- finished with flat array, do next element of multi-d array+ write ns [] ((n, vs):nvss) !i = write (n:ns) vs nvss i++ -- done+ write _ _ [] _ = pure ()+++ write sizes [val] [] 0+ runEval stk $ f [SomeFFIArg ptr]++ marshalArg (FFITuple types) val f =+ do vals <- sequence (fromVTuple val)+ marshalArgs (types `zip` vals) f++ marshalArg (FFIRecord typeMap) val f =+ do vals <- traverse (`lookupRecord` val) (displayOrder typeMap)+ marshalArgs (displayElements typeMap `zip` vals) f++ -- Call marshalArg on a bunch of arguments and collect the results together+ -- (in the order of the arguments).+ marshalArgs ::+ [(FFIType, GenValue Concrete)] ->+ ([SomeFFIArg] -> Eval a) ->+ Eval a+ marshalArgs typesAndVals f = go typesAndVals []+ where+ go [] args = f (concat (reverse args))+ go ((t, v):tvs) prevArgs =+ marshalArg t v \currArgs ->+ go tvs (currArgs : prevArgs)++ -- Given an FFIType and a GetRet, obtain a return value and convert it to a+ -- Cryptol value. The return value is obtained differently depending on the+ -- FFIType.+ marshalRet :: FFIType -> GetRet -> Eval (GenValue Concrete)+ marshalRet FFIBool gr =+ do rep <- io (getRetAsValue gr @Word8)+ pure (VBit (toBool rep))++ marshalRet (FFIBasic (FFIBasicVal t)) gr =+ getMarshalBasicValRet t \doImport ->+ do rep <- io (getRetAsValue gr)+ doImport rep++ marshalRet (FFIBasic (FFIBasicRef t)) gr =+ getBasicRefRet t \how ->+ Eval \stk ->+ alloca \ptr ->+ bracket_ (initBasicRefRet how ptr) (clearBasicRefRet how ptr)+ do getRetAsOutArgs gr [SomeFFIArg ptr]+ rep <- peek ptr+ runEval stk (marshalBasicRefRet how rep)++ marshalRet (FFIArray (map evalFinType -> sizes) bt) gr =+ Eval \stk -> do+ let totalSize = fromInteger (product sizes)+ getResult marshal ptr = do+ getRetAsOutArgs gr [SomeFFIArg ptr]++ let build (n:ns) !i = do+ -- We need to be careful to actually run this here and not just+ -- stick the IO action into the sequence with io, or else we+ -- will read from the array after it is deallocated.+ vs <- for [0 .. fromInteger n - 1] \j ->+ build ns (i * fromInteger n + j)+ pure (VSeq n (finiteSeqMap Concrete (map pure vs)))+ build [] !i = peekElemOff ptr i >>= runEval stk . marshal++ build sizes 0++ case bt of++ FFIBasicVal t ->+ getMarshalBasicValRet t \doImport ->+ allocaArray totalSize (getResult doImport)++ FFIBasicRef t ->+ getBasicRefRet t \how ->+ allocaArray totalSize \ptr ->+ do let forEach f = for_ [0 .. totalSize - 1] (f . advancePtr ptr)+ bracket_ (forEach (initBasicRefRet how))+ (forEach (clearBasicRefRet how))+ (getResult (marshalBasicRefRet how) ptr)++ marshalRet (FFITuple types) gr = VTuple <$> marshalMultiRet types gr++ marshalRet (FFIRecord typeMap) gr =+ VRecord . recordFromFields . zip (displayOrder typeMap) <$>+ marshalMultiRet (displayElements typeMap) gr++ -- Obtain multiple return values as output arguments for a composite return+ -- type. Each return value is fully evaluated but put back in an Eval since+ -- VTuple and VRecord expect it.+ marshalMultiRet :: [FFIType] -> GetRet -> Eval [Eval (GenValue Concrete)]+ -- Since IO callbacks are involved we just do the whole thing in IO and wrap+ -- it in an Eval at the end. This should be fine since we are not changing+ -- the (Cryptol) call stack.+ marshalMultiRet types gr = Eval \stk -> do+ -- We use this IORef hack here since we are calling marshalRet recursively+ -- but marshalRet doesn't let us return any extra information from the+ -- callback through to the result of the function. So we remember the result+ -- as a side effect.+ vals <- newIORef []+ let go [] args = getRetAsOutArgs gr args+ go (t:ts) prevArgs = do+ val <- runEval stk $ marshalRet t $ getRetFromAsOutArgs \currArgs ->+ go ts (prevArgs ++ currArgs)+ modifyIORef' vals (val :)+ go types []+ map pure <$> readIORef vals++ -- | Call the callback with a 'BasicRefRet' for the given type.+ getBasicRefRet :: FFIBasicRefType ->+ (forall a. Storable a => BasicRefRet a -> b) -> b+ getBasicRefRet (FFIInteger mbMod) f = f BasicRefRet+ { initBasicRefRet = mpz_init+ , clearBasicRefRet = mpz_clear+ , marshalBasicRefRet = \mpz -> do+ n <- io $ peekInteger' mpz+ VInteger <$>+ case mbMod of+ Nothing -> pure n+ Just m -> intToZn Concrete (evalFinType m) n }+ getBasicRefRet FFIRational f = f BasicRefRet+ { initBasicRefRet = mpq_init+ , clearBasicRefRet = mpq_clear+ , marshalBasicRefRet = \mpq -> do+ r <- io $ peekRational' mpq+ pure $ VRational $ SRational (numerator r) (denominator r) }++ -- Evaluate a finite numeric type expression.+ evalFinType :: Type -> Integer+ evalFinType = finNat' . evalNumType tenv++-- | Given a way to 'getRetAsOutArgs', create a 'GetRet', where the+-- 'getRetAsValue' simply allocates a temporary space to call 'getRetAsOutArgs'+-- on. This is useful for return types that we know how to obtain directly as a+-- value but need to obtain as an output argument when multiple return values+-- are involved.+getRetFromAsOutArgs :: ([SomeFFIArg] -> IO ()) -> GetRet+getRetFromAsOutArgs f = GetRet+ { getRetAsValue = alloca \ptr -> do+ f [SomeFFIArg ptr]+ peek ptr+ , getRetAsOutArgs = f }++-- | Given a 'FFIBasicValType', call the callback with a marshalling function+-- that marshals values to the 'FFIArg' type corresponding to the+-- 'FFIBasicValType'. The callback must be able to handle marshalling functions+-- that marshal to any 'FFIArg' type.+getMarshalBasicValArg ::+ FFIBasicValType ->+ (forall rep.+ FFIArg rep =>+ (GenValue Concrete -> Eval rep) ->+ result) ->+ result++getMarshalBasicValArg (FFIWord _ s) f = withWordType s \(_ :: p t) ->+ f @t $ fmap (fromInteger . bvVal) . fromVWord Concrete "getMarshalBasicValArg"++getMarshalBasicValArg (FFIFloat _ _ s) f =+ case s of+ -- LibBF can only convert to 'Double' directly, so we do that first then+ -- convert to 'Float', which should not result in any loss of precision if+ -- the original data was 32-bit anyways.+ FFIFloat32 -> f $ pure . CFloat . double2Float . toDouble+ FFIFloat64 -> f $ pure . CDouble . toDouble+ where+ toDouble = fst . bfToDouble NearEven . bfValue . fromVFloat++-- | Given a 'FFIBasicValType', call the callback with an unmarshalling function+-- from the 'FFIRet' type corresponding to the 'FFIBasicValType' to Cryptol+-- values. The callback must be able to handle unmarshalling functions from any+-- 'FFIRet' type.+getMarshalBasicValRet :: FFIBasicValType ->+ (forall a. FFIRet a => (a -> Eval (GenValue Concrete)) -> b) -> b+getMarshalBasicValRet (FFIWord n s) f = withWordType s \(_ :: p t) ->+ f @t $ word Concrete n . toInteger+getMarshalBasicValRet (FFIFloat e p s) f =+ case s of+ FFIFloat32 -> f $ toValue . \case CFloat x -> float2Double x+ FFIFloat64 -> f $ toValue . \case CDouble x -> x+ where toValue = pure . VFloat . BF e p . bfFromDouble++-- | Call the callback with the Word type corresponding to the given+-- 'FFIWordSize'.+withWordType :: FFIWordSize ->+ (forall a. (FFIArg a, FFIRet a, Integral a) => Proxy a -> b) -> b+withWordType FFIWord8 f = f $ Proxy @Word8+withWordType FFIWord16 f = f $ Proxy @Word16+withWordType FFIWord32 f = f $ Proxy @Word32+withWordType FFIWord64 f = f $ Proxy @Word64++-- | Given a 'FFIBasicRefType', call the callback with a marshalling function+-- that takes a Cryptol value and calls its callback with the 'Storable' type+-- corresponding to the 'FFIBasicRefType'.+getMarshalBasicRefArg :: FFIBasicRefType ->+ (forall rep.+ Storable rep =>+ (GenValue Concrete -> (rep -> IO val) -> IO val) ->+ result) ->+ result+getMarshalBasicRefArg (FFIInteger _) f = f \val g ->+ withInInteger' (fromVInteger val) g+getMarshalBasicRefArg FFIRational f = f \val g -> do+ let SRational {..} = fromVRational val+ withInRational' (sNum % sDenom) g++#else++-- | Dummy implementation for when FFI is disabled. Does not add anything to+-- the environment.+evalForeignDecls :: ForeignSrc -> [(Name, FFIFunType)] -> EvalEnv ->+ Eval (Either [FFILoadError] EvalEnv)+evalForeignDecls _ _ env = pure $ Right env++#endif
+ src/Cryptol/Eval/FFI/GenHeader.hs view
@@ -0,0 +1,196 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeApplications #-}++-- | Generate C header files from foreign declarations.+module Cryptol.Eval.FFI.GenHeader+ ( generateForeignHeader+ ) where++import Control.Monad.Writer.Strict+import Data.Functor+import Data.Char(isAlphaNum)+import Data.List+import Data.Set (Set)+import qualified Data.Set as Set+import Language.C99.Pretty as C+import qualified Language.C99.Simple as C+import qualified Text.PrettyPrint as Pretty++import Cryptol.ModuleSystem.Name+import Cryptol.TypeCheck.FFI.FFIType+import Cryptol.TypeCheck.Type+import Cryptol.Utils.Ident+import Cryptol.Utils.RecordMap++-- | @Include foo@ represents an include statement @#include <foo>@+newtype Include = Include String deriving (Eq, Ord)++-- | The monad for generating headers. We keep track of which headers we need to+-- include and add them to the output at the end.+type GenHeaderM = Writer (Set Include)++-- | Generate a C header file from the given foreign declarations.+generateForeignHeader :: [(Name, FFIFunType)] -> String+generateForeignHeader decls =+ unlines (map renderInclude $ Set.toAscList incs)+ ++ Pretty.render (C.pretty $ C.translate (C.TransUnit cdecls []))+ where (cdecls, incs) = runWriter $ traverse convertFun decls++renderInclude :: Include -> String+renderInclude (Include inc) = "#include <" ++ inc ++ ">"++-- | The "direction" of a parameter (input or output).+data ParamDir = In | Out++-- | The result of converting a Cryptol type into its C representation.+data ConvertResult+ = Direct C.Type -- ^ A type that can be directly returned if it is a return+ -- type and passed as a single parameter if it is a Cryptol+ -- parameter type.+ | Params [C.Param] -- ^ A type that is turned into a number of parameters,+ -- for both Cryptol parameter and return type cases.++-- | Convert a Cryptol foreign declaration into a C function declaration.+convertFun :: (Name, FFIFunType) -> GenHeaderM C.Decln+convertFun (fName, FFIFunType {..}) = do+ let tpIdent = fmap nameIdent . tpName+ typeParams <- traverse convertTypeParam (pickNames (map tpIdent ffiTParams))+ -- Name the input args in0, in1, etc+ let inPrefixes =+ case ffiArgTypes of+ [_] -> ["in"]+ _ -> ["in" ++ show @Integer i | i <- [0..]]+ inParams <- convertMultiType In $ zip inPrefixes ffiArgTypes+ (retType, outParams) <- convertType Out ffiRetType+ <&> \case+ Direct u -> (u, [])+ -- Name the output arg out+ Params ps -> (C.TypeSpec C.Void, map (prefixParam "out") ps)+ -- Avoid possible name collisions+ let params = snd $ mapAccumL renameParam Set.empty $+ typeParams ++ inParams ++ outParams+ renameParam names (C.Param u name) =+ (Set.insert name' names, C.Param u name')+ where name' = until (`Set.notMember` names) (++ "_") name+ pure $ C.FunDecln Nothing retType (unpackIdent $ nameIdent fName) params+++-- | Convert a Cryptol type parameter to a C value parameter.+convertTypeParam :: String -> GenHeaderM C.Param+convertTypeParam name = (`C.Param` name) <$> sizeT++-- | Convert a Cryptol parameter or return type to C.+convertType :: ParamDir -> FFIType -> GenHeaderM ConvertResult+convertType _ FFIBool = Direct <$> uint8T+convertType _ (FFIBasic t) = convertBasicType t+convertType _ (FFIArray _ t) = do+ u <- convertBasicTypeInArray t+ pure $ Params [C.Param (C.Ptr u) ""]+convertType dir (FFITuple ts) = Params <$> convertMultiType dir+ -- We name the tuple components using their indices+ (zip (map (componentSuffix . show @Integer) [0..]) ts)+convertType dir (FFIRecord tMap) =+ Params <$> convertMultiType dir (zip names ts)+ where+ (fs,ts) = unzip (displayFields tMap)+ names = map componentSuffix (pickNames (map Just fs))++-- | Convert many Cryptol types, each associated with a prefix, to C parameters+-- named with their prefixes.+convertMultiType :: ParamDir -> [(C.Ident, FFIType)] -> GenHeaderM [C.Param]+convertMultiType dir = fmap concat . traverse \(prefix, t) ->+ convertType dir t+ <&> \case+ Direct u -> [C.Param u' prefix]+ where u' = case dir of+ In -> u+ -- Turn direct return types into pointer out parameters+ Out -> C.Ptr u+ Params ps -> map (prefixParam prefix) ps++{- | Convert a basic Cryptol FFI type to a C type with its corresponding+calling convention. At present all value types use the same calling+convention no matter if they are inputs or outputs, so we don't+need the 'ParamDir'. -}+convertBasicType :: FFIBasicType -> GenHeaderM ConvertResult+convertBasicType bt =+ case bt of+ FFIBasicVal bvt -> Direct <$> convertBasicValType bvt+ FFIBasicRef brt -> do t <- convertBasicRefType brt+ pure (Params [C.Param t ""])++-- | Convert a basic Cryptol FFI type to a C type.+-- This is used when the type is stored in array.+convertBasicTypeInArray :: FFIBasicType -> GenHeaderM C.Type+convertBasicTypeInArray bt =+ case bt of+ FFIBasicVal bvt -> convertBasicValType bvt+ FFIBasicRef brt -> convertBasicRefType brt++-- | Convert a basic Cryptol FFI type to a value C type.+convertBasicValType :: FFIBasicValType -> GenHeaderM C.Type+convertBasicValType (FFIWord _ s) =+ case s of+ FFIWord8 -> uint8T+ FFIWord16 -> uint16T+ FFIWord32 -> uint32T+ FFIWord64 -> uint64T+convertBasicValType (FFIFloat _ _ s) =+ case s of+ FFIFloat32 -> pure $ C.TypeSpec C.Float+ FFIFloat64 -> pure $ C.TypeSpec C.Double++-- | Convert a basic Cryptol FFI type to a reference C type.+convertBasicRefType :: FFIBasicRefType -> GenHeaderM C.Type+convertBasicRefType brt =+ case brt of+ FFIInteger {} -> mpzT+ FFIRational -> mpqT++prefixParam :: C.Ident -> C.Param -> C.Param+prefixParam pre (C.Param u name) = C.Param u (pre ++ name)++-- | Create a suffix corresponding to some component name of some larger type.+componentSuffix :: String -> C.Ident+componentSuffix = ('_' :)++sizeT, uint8T, uint16T, uint32T, uint64T, mpzT, mpqT :: GenHeaderM C.Type+sizeT = typedefFromInclude stddefH "size_t"+uint8T = typedefFromInclude stdintH "uint8_t"+uint16T = typedefFromInclude stdintH "uint16_t"+uint32T = typedefFromInclude stdintH "uint32_t"+uint64T = typedefFromInclude stdintH "uint64_t"+mpzT = typedefFromInclude gmpH "mpz_t"+mpqT = typedefFromInclude gmpH "mpq_t"++stddefH, stdintH, gmpH :: Include+stddefH = Include "stddef.h"+stdintH = Include "stdint.h"+gmpH = Include "gmp.h"+++-- | Return a type with the given name, included from some header file.+typedefFromInclude :: Include -> C.Ident -> GenHeaderM C.Type+typedefFromInclude inc u = do+ tell $ Set.singleton inc+ pure $ C.TypeSpec $ C.TypedefName u++-- | Given some Cryptol identifiers (normal ones, not operators)+-- pick suitable unique C names for them+pickNames :: [Maybe Ident] -> [String]+pickNames xs = snd (mapAccumL add Set.empty xs)+ where+ add known x =+ let y = simplify x+ ys = y : [ y ++ show i | i <- [ 0 :: Int .. ] ]+ y' : _ = dropWhile (`Set.member` known) ys+ in (Set.insert y' known, y')++ simplify x = case x of+ Just i | let y = filter ok (unpackIdent i), not (null y) -> y+ _ -> "zz"++ ok x = x == '_' || isAlphaNum x+
src/Cryptol/Eval/Generic.hs view
@@ -1452,12 +1452,12 @@ PNumPoly \first -> PNumPoly \lst -> PTyPoly \ty ->- PVal+ PPrim let !f = mkLit sym ty in case (first, lst) of (Nat first', Nat lst') -> let len = 1 + (lst' - first')- in VSeq len $ indexSeqMap $ \i -> f (first' + i)+ in mkSeq sym (Nat len) ty $ indexSeqMap $ \i -> f (first' + i) _ -> evalPanic "fromToV" ["invalid arguments"] {-# INLINE fromThenToV #-}@@ -1469,12 +1469,12 @@ PNumPoly \lst -> PTyPoly \ty -> PNumPoly \len ->- PVal+ PPrim let !f = mkLit sym ty in case (first, next, lst, len) of (Nat first', Nat next', Nat _lst', Nat len') -> let diff = next' - first'- in VSeq len' $ indexSeqMap $ \i -> f (first' + i*diff)+ in mkSeq sym (Nat len') ty $ indexSeqMap $ \i -> f (first' + i*diff) _ -> evalPanic "fromThenToV" ["invalid arguments"] {-# INLINE fromToLessThanV #-}@@ -1484,12 +1484,12 @@ PFinPoly \first -> PNumPoly \bound -> PTyPoly \ty ->- PVal+ PPrim let !f = mkLit sym ty ss = indexSeqMap $ \i -> f (first + i) in case bound of- Inf -> VStream ss- Nat bound' -> VSeq (bound' - first) ss+ Inf -> return $ VStream ss+ Nat bound' -> mkSeq sym (Nat (bound' - first)) ty ss {-# INLINE fromToByV #-} -- @[ 0 .. 10 by 2 ]@@@ -1499,10 +1499,10 @@ PFinPoly \lst -> PFinPoly \stride -> PTyPoly \ty ->- PVal+ PPrim let !f = mkLit sym ty ss = indexSeqMap $ \i -> f (first + i*stride)- in VSeq (1 + ((lst - first) `div` stride)) ss+ in mkSeq sym (Nat (1 + ((lst - first) `div` stride))) ty ss {-# INLINE fromToByLessThanV #-} -- @[ 0 .. <10 by 2 ]@@@ -1512,12 +1512,12 @@ PNumPoly \bound -> PFinPoly \stride -> PTyPoly \ty ->- PVal+ PPrim let !f = mkLit sym ty ss = indexSeqMap $ \i -> f (first + i*stride) in case bound of- Inf -> VStream ss- Nat bound' -> VSeq ((bound' - first + stride - 1) `div` stride) ss+ Inf -> return $ VStream ss+ Nat bound' -> mkSeq sym (Nat ((bound' - first + stride - 1) `div` stride)) ty ss {-# INLINE fromToDownByV #-}@@ -1528,10 +1528,10 @@ PFinPoly \lst -> PFinPoly \stride -> PTyPoly \ty ->- PVal+ PPrim let !f = mkLit sym ty ss = indexSeqMap $ \i -> f (first - i*stride)- in VSeq (1 + ((first - lst) `div` stride)) ss+ in mkSeq sym (Nat (1 + ((first - lst) `div` stride))) ty ss {-# INLINE fromToDownByGreaterThanV #-} -- @[ 10 .. >0 down by 2 ]@@@ -1541,10 +1541,10 @@ PFinPoly \bound -> PFinPoly \stride -> PTyPoly \ty ->- PVal+ PPrim let !f = mkLit sym ty ss = indexSeqMap $ \i -> f (first - i*stride)- in VSeq ((first - bound + stride - 1) `div` stride) ss+ in mkSeq sym (Nat ((first - bound + stride - 1) `div` stride)) ty ss {-# INLINE infFromV #-} infFromV :: Backend sym => sym -> Prim sym
src/Cryptol/Eval/Reference.lhs view
@@ -10,6 +10,8 @@ > {-# LANGUAGE BlockArguments #-} > {-# LANGUAGE PatternGuards #-} > {-# LANGUAGE LambdaCase #-}+> {-# LANGUAGE NamedFieldPuns #-}+> {-# LANGUAGE ViewPatterns #-} > > module Cryptol.Eval.Reference > ( Value(..)@@ -32,6 +34,7 @@ > import LibBF (BigFloat) > import qualified LibBF as FP > import qualified GHC.Num.Compat as Integer+> import qualified Data.List as List > > import Cryptol.ModuleSystem.Name (asPrim) > import Cryptol.TypeCheck.Solver.InfNat (Nat'(..), nAdd, nMin, nMul)@@ -46,6 +49,8 @@ > import Cryptol.Utils.Panic (panic) > import Cryptol.Utils.PP > import Cryptol.Utils.RecordMap+> import Cryptol.Eval (checkProp)+> import Cryptol.Eval.Type (evalType, lookupTypeVar, tNumTy, tValTy) > > import qualified Cryptol.ModuleSystem as M > import qualified Cryptol.ModuleSystem.Env as M (loadedModules,loadedNewtypes)@@ -332,12 +337,28 @@ > EProofAbs _ e -> evalExpr env e > EProofApp e -> evalExpr env e > EWhere e dgs -> evalExpr (foldl evalDeclGroup env dgs) e-+>+> EPropGuards guards _ty -> +> case List.find (all (checkProp . evalProp env) . fst) guards of+> Just (_, e) -> evalExpr env e+> Nothing -> evalPanic "fromVBit" ["No guard constraint was satisfied"] > appFun :: E Value -> E Value -> E Value > appFun f v = f >>= \f' -> fromVFun f' v +> -- | Evaluates a `Prop` in an `EvalEnv` by substituting all variables +> -- according to `envTypes` and expanding all type synonyms via `tNoUser`.+> evalProp :: Env -> Prop -> Prop+> evalProp env@Env { envTypes } = \case+> TCon tc tys -> TCon tc (toType . evalType envTypes <$> tys)+> TVar tv | Just (toType -> ty) <- lookupTypeVar tv envTypes -> ty+> prop@TUser {} -> evalProp env (tNoUser prop)+> TVar tv | Nothing <- lookupTypeVar tv envTypes -> panic "evalProp" ["Could not find type variable `" ++ pretty tv ++ "` in the type evaluation environment"]+> prop -> panic "evalProp" ["Cannot use the following as a type constraint: `" ++ pretty prop ++ "`"]+> where +> toType = either tNumTy tValTy + Selectors --------- @@ -510,8 +531,9 @@ > evalDecl :: Env -> Decl -> (Name, E Value) > evalDecl env d = > case dDefinition d of-> DPrim -> (dName d, pure (evalPrim (dName d)))-> DExpr e -> (dName d, evalExpr env e)+> DPrim -> (dName d, pure (evalPrim (dName d)))+> DForeign _ -> (dName d, cryError $ FFINotSupported $ dName d)+> DExpr e -> (dName d, evalExpr env e) > Newtypes@@ -523,7 +545,7 @@ that consumes and ignores its type arguments. > evalNewtypeDecl :: Env -> Newtype -> Env-> evalNewtypeDecl env nt = bindVar (ntName nt, pure val) env+> evalNewtypeDecl env nt = bindVar (ntConName nt, pure val) env > where > val = foldr tabs con (ntParams nt) > con = VFun (\x -> x)
src/Cryptol/Eval/SBV.hs view
@@ -8,6 +8,7 @@ {-# LANGUAGE BlockArguments #-} {-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-}
src/Cryptol/Eval/Type.hs view
@@ -18,6 +18,7 @@ import Cryptol.Utils.Panic (panic) import Cryptol.Utils.Ident (Ident) import Cryptol.Utils.RecordMap+import Cryptol.Utils.Types import Data.Maybe(fromMaybe) import qualified Data.IntMap.Strict as IntMap@@ -27,7 +28,7 @@ -- | An evaluated type of kind *. -- These types do not contain type variables, type synonyms, or type functions. data TValue- = TVBit -- ^ @ Bit @+ = TVBit -- ^ @ Bit @ | TVInteger -- ^ @ Integer @ | TVFloat Integer Integer -- ^ @ Float e p @ | TVIntMod Integer -- ^ @ Z n @@@ -86,6 +87,10 @@ tvSeq (Nat n) t = TVSeq n t tvSeq Inf t = TVStream t +-- | The Cryptol @Float64@ type.+tvFloat64 :: TValue+tvFloat64 = uncurry TVFloat float64ExpPrec+ -- | Coerce an extended natural into an integer, -- for values known to be finite finNat' :: Nat' -> Integer@@ -100,6 +105,7 @@ newtype TypeEnv = TypeEnv { envTypeMap :: IntMap.IntMap (Either Nat' TValue) }+ deriving (Show) instance Monoid TypeEnv where mempty = TypeEnv mempty
src/Cryptol/Eval/What4.hs view
@@ -6,6 +6,7 @@ {-# LANGUAGE BlockArguments #-} {-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiWayIf #-}@@ -505,7 +506,7 @@ TValue -> SInteger (What4 sym) -> SEval (What4 sym) (Value sym)-indexFront_int sym mblen _a xs ix idx+indexFront_int sym mblen _a xs _ix idx | Just i <- W4.asInteger idx = lookupSeqMap xs i @@ -535,16 +536,13 @@ _ -> Nothing ) - -- Maximum possible in-bounds index given `Z m`- -- type information and the length- -- of the sequence. If the sequences is infinite and the- -- integer is unbounded, there isn't much we can do.+ -- Maximum possible in-bounds index given the length+ -- of the sequence. If the sequence is infinite, there+ -- isn't much we can do. maxIdx =- case (mblen, ix) of- (Nat n, TVIntMod m) -> Just (min (toInteger n) (toInteger m))- (Nat n, _) -> Just n- (_ , TVIntMod m) -> Just m- _ -> Nothing+ case mblen of+ Nat n -> Just (n - 1)+ Inf -> Nothing indexFront_segs :: W4.IsSymExprBuilder sym => What4 sym ->
src/Cryptol/IR/FreeVars.hs view
@@ -93,6 +93,7 @@ instance FreeVars DeclDef where freeVars d = case d of DPrim -> mempty+ DForeign _ -> mempty DExpr e -> freeVars e @@ -116,6 +117,7 @@ EProofAbs p e -> freeVars p <> freeVars e EProofApp e -> freeVars e EWhere e ds -> foldFree ds <> rmVals (defs ds) (freeVars e)+ EPropGuards guards _ -> mconcat [ freeVars e | (_, e) <- guards ] where foldFree :: (FreeVars a, Defs a) => [a] -> Deps foldFree = foldr updateFree mempty
+ src/Cryptol/IR/TraverseNames.hs view
@@ -0,0 +1,267 @@+{-# Language ImplicitParams #-}+module Cryptol.IR.TraverseNames where++import Data.Set(Set)+import qualified Data.Set as Set+import Data.Functor.Identity++import Cryptol.ModuleSystem.Name(nameUnique)+import Cryptol.Utils.RecordMap(traverseRecordMap)+import Cryptol.Parser.Position(Located(..))+import Cryptol.TypeCheck.AST+import Cryptol.TypeCheck.FFI.FFIType++traverseNames ::+ (TraverseNames t, Applicative f) => (Name -> f Name) -> (t -> f t)+traverseNames f = let ?name = f in traverseNamesIP++mapNames :: (TraverseNames t) => (Name -> Name) -> t -> t+mapNames f x = result+ where+ Identity result = let ?name = pure . f+ in traverseNamesIP x++class TraverseNames t where+ traverseNamesIP :: (Applicative f, ?name :: Name -> f Name) => t -> f t++instance TraverseNames a => TraverseNames [a] where+ traverseNamesIP = traverse traverseNamesIP++instance TraverseNames a => TraverseNames (Maybe a) where+ traverseNamesIP = traverse traverseNamesIP++instance (Ord a, TraverseNames a) => TraverseNames (Set a) where+ traverseNamesIP = fmap Set.fromList . traverseNamesIP . Set.toList++instance TraverseNames a => TraverseNames (Located a) where+ traverseNamesIP (Located r a) = Located r <$> traverseNamesIP a++instance TraverseNames Name where+ traverseNamesIP = ?name++instance (Ord a, TraverseNames a) => TraverseNames (ExportSpec a) where+ traverseNamesIP (ExportSpec mp) = ExportSpec <$> traverse traverseNamesIP mp++instance TraverseNames Expr where+ traverseNamesIP expr =+ case expr of+ EList es t -> EList <$> traverseNamesIP es <*> traverseNamesIP t++ ETuple es -> ETuple <$> traverseNamesIP es++ ERec mp -> ERec <$> traverseRecordMap (\_ -> traverseNamesIP) mp++ ESel e l -> (`ESel` l) <$> traverseNamesIP e++ ESet t e1 l e2 -> ESet <$> traverseNamesIP t+ <*> traverseNamesIP e1+ <*> pure l+ <*> traverseNamesIP e2++ EIf e1 e2 e3 -> EIf <$> traverseNamesIP e1+ <*> traverseNamesIP e2+ <*> traverseNamesIP e3++ EComp t1 t2 e mss -> EComp <$> traverseNamesIP t1+ <*> traverseNamesIP t2+ <*> traverseNamesIP e+ <*> traverseNamesIP mss++ EVar x -> EVar <$> traverseNamesIP x+ ETAbs tp e -> ETAbs <$> traverseNamesIP tp <*> traverseNamesIP e+ ETApp e t -> ETApp <$> traverseNamesIP e <*> traverseNamesIP t+ EApp e1 e2 -> EApp <$> traverseNamesIP e1 <*> traverseNamesIP e2+ EAbs x t e -> EAbs <$> traverseNamesIP x+ <*> traverseNamesIP t+ <*> traverseNamesIP e+ ELocated r e -> ELocated r <$> traverseNamesIP e+ EProofAbs p e -> EProofAbs <$> traverseNamesIP p <*> traverseNamesIP e+ EProofApp e -> EProofApp <$> traverseNamesIP e+ EWhere e ds -> EWhere <$> traverseNamesIP e <*> traverseNamesIP ds++ EPropGuards gs t -> EPropGuards <$> traverse doG gs <*> traverseNamesIP t+ where doG (xs, e) = (,) <$> traverseNamesIP xs <*> traverseNamesIP e++instance TraverseNames Match where+ traverseNamesIP mat =+ case mat of+ From x t1 t2 e -> From <$> traverseNamesIP x+ <*> traverseNamesIP t1+ <*> traverseNamesIP t2+ <*> traverseNamesIP e+ Let d -> Let <$> traverseNamesIP d++instance TraverseNames DeclGroup where+ traverseNamesIP dg =+ case dg of+ NonRecursive d -> NonRecursive <$> traverseNamesIP d+ Recursive ds -> Recursive <$> traverseNamesIP ds++instance TraverseNames Decl where+ traverseNamesIP decl = mk <$> traverseNamesIP (dName decl)+ <*> traverseNamesIP (dSignature decl)+ <*> traverseNamesIP (dDefinition decl)+ where mk nm sig def = decl { dName = nm+ , dSignature = sig+ , dDefinition = def+ }++instance TraverseNames DeclDef where+ traverseNamesIP d =+ case d of+ DPrim -> pure d+ DForeign t -> DForeign <$> traverseNamesIP t+ DExpr e -> DExpr <$> traverseNamesIP e++instance TraverseNames Schema where+ traverseNamesIP (Forall as ps t) =+ Forall <$> traverseNamesIP as+ <*> traverseNamesIP ps+ <*> traverseNamesIP t++instance TraverseNames TParam where+ traverseNamesIP tp = mk <$> traverseNamesIP (tpFlav tp)+ <*> traverseNamesIP (tpInfo tp)+ -- XXX: module parameters should probably be represented directly+ -- as (abstract) user-defined types, rather than type variables.+ where mk f i = case f of+ TPModParam x ->+ tp { tpUnique = nameUnique x, tpFlav = f, tpInfo = i }+ _ -> tp { tpFlav = f, tpInfo = i }+++instance TraverseNames TPFlavor where+ traverseNamesIP tpf =+ case tpf of+ TPModParam x -> TPModParam <$> traverseNamesIP x+ TPUnifyVar -> pure tpf+ TPSchemaParam x -> TPSchemaParam <$> traverseNamesIP x+ TPTySynParam x -> TPTySynParam <$> traverseNamesIP x+ TPPropSynParam x -> TPPropSynParam <$> traverseNamesIP x+ TPNewtypeParam x -> TPNewtypeParam <$> traverseNamesIP x+ TPPrimParam x -> TPPrimParam <$> traverseNamesIP x++instance TraverseNames TVarInfo where+ traverseNamesIP (TVarInfo r s) = TVarInfo r <$> traverseNamesIP s++instance TraverseNames TypeSource where+ traverseNamesIP src =+ case src of+ TVFromModParam x -> TVFromModParam <$> traverseNamesIP x+ TVFromSignature x -> TVFromSignature <$> traverseNamesIP x+ TypeWildCard -> pure src+ TypeOfRecordField {} -> pure src+ TypeOfTupleField {} -> pure src+ TypeOfSeqElement -> pure src+ LenOfSeq -> pure src+ TypeParamInstNamed x i -> TypeParamInstNamed <$> traverseNamesIP x+ <*> pure i+ TypeParamInstPos x i -> TypeParamInstPos <$> traverseNamesIP x+ <*> pure i+ DefinitionOf x -> DefinitionOf <$> traverseNamesIP x+ LenOfCompGen -> pure src+ TypeOfArg arg -> TypeOfArg <$> traverseNamesIP arg+ TypeOfRes -> pure src+ FunApp -> pure src+ TypeOfIfCondExpr -> pure src+ TypeFromUserAnnotation -> pure src+ GeneratorOfListComp -> pure src+ TypeErrorPlaceHolder -> pure src++instance TraverseNames ArgDescr where+ traverseNamesIP arg = mk <$> traverseNamesIP (argDescrFun arg)+ where mk n = arg { argDescrFun = n }++instance TraverseNames Type where+ traverseNamesIP ty =+ case ty of+ TCon tc ts -> TCon <$> traverseNamesIP tc <*> traverseNamesIP ts+ TVar x -> TVar <$> traverseNamesIP x+ TUser x ts t -> TUser <$> traverseNamesIP x+ <*> traverseNamesIP ts+ <*> traverseNamesIP t+ TRec rm -> TRec <$> traverseRecordMap (\_ -> traverseNamesIP) rm+ TNewtype nt ts -> TNewtype <$> traverseNamesIP nt <*> traverseNamesIP ts+++instance TraverseNames TCon where+ traverseNamesIP tcon =+ case tcon of+ TC tc -> TC <$> traverseNamesIP tc+ _ -> pure tcon++instance TraverseNames TC where+ traverseNamesIP tc =+ case tc of+ TCAbstract ut -> TCAbstract <$> traverseNamesIP ut+ _ -> pure tc++instance TraverseNames UserTC where+ traverseNamesIP (UserTC x k) = UserTC <$> traverseNamesIP x <*> pure k++instance TraverseNames TVar where+ traverseNamesIP tvar =+ case tvar of+ TVFree x k ys i -> TVFree x k <$> traverseNamesIP ys <*> traverseNamesIP i+ TVBound x -> TVBound <$> traverseNamesIP x++instance TraverseNames Newtype where+ traverseNamesIP nt = mk <$> traverseNamesIP (ntName nt)+ <*> traverseNamesIP (ntParams nt)+ <*> traverseNamesIP (ntConstraints nt)+ <*> traverseNamesIP (ntConName nt)+ <*> traverseRecordMap (\_ -> traverseNamesIP)+ (ntFields nt)+ where+ mk a b c d e = nt { ntName = a+ , ntParams = b+ , ntConstraints = c+ , ntConName = d+ , ntFields = e+ }++instance TraverseNames ModTParam where+ traverseNamesIP nt = mk <$> traverseNamesIP (mtpName nt)+ where+ mk x = nt { mtpName = x }++instance TraverseNames ModVParam where+ traverseNamesIP nt = mk <$> traverseNamesIP (mvpName nt)+ <*> traverseNamesIP (mvpType nt)+ where+ mk x t = nt { mvpName = x, mvpType = t }++instance TraverseNames FFIFunType where+ traverseNamesIP fi = mk <$> traverseNamesIP (ffiArgTypes fi)+ <*> traverseNamesIP (ffiRetType fi)+ where+ mk as b =+ FFIFunType+ { ffiTParams = ffiTParams fi+ , ffiArgTypes = as+ , ffiRetType = b+ }++instance TraverseNames FFIType where+ traverseNamesIP ft =+ case ft of+ FFIBool -> pure ft+ FFIBasic _ -> pure ft -- assumes no names here+ FFIArray sz t -> (`FFIArray` t) <$> traverseNamesIP sz+ FFITuple ts -> FFITuple <$> traverseNamesIP ts+ FFIRecord mp -> FFIRecord <$> traverseRecordMap+ (\_ -> traverseNamesIP) mp+instance TraverseNames TySyn where+ traverseNamesIP ts = mk <$> traverseNamesIP (tsName ts)+ <*> traverseNamesIP (tsParams ts)+ <*> traverseNamesIP (tsConstraints ts)+ <*> traverseNamesIP (tsDef ts)+ where mk n ps cs t =+ TySyn { tsName = n+ , tsParams = ps+ , tsConstraints = cs+ , tsDef = t+ , tsDoc = tsDoc ts+ }++
src/Cryptol/ModuleSystem.hs view
@@ -7,6 +7,7 @@ -- Portability : portable {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE BlockArguments #-} module Cryptol.ModuleSystem ( -- * Module System@@ -18,8 +19,10 @@ , findModule , loadModuleByPath , loadModuleByName+ , checkModuleByPath , checkExpr , evalExpr+ , benchmarkExpr , checkDecls , evalDecls , noPat@@ -29,8 +32,11 @@ , renameType -- * Interfaces- , Iface, IfaceG(..), IfaceParams(..), IfaceDecls(..), T.genIface- , IfaceTySyn, IfaceDecl(..)+ , Iface, IfaceG(..), IfaceDecls(..), T.genIface, IfaceDecl(..)++ -- * Dependencies+ , getFileDependencies+ , getModuleDependencies ) where import Data.Map (Map)@@ -47,6 +53,7 @@ import Cryptol.Parser.NoPat (RemovePatterns) import qualified Cryptol.TypeCheck.AST as T import qualified Cryptol.TypeCheck.Interface as T+import Cryptol.Utils.Benchmark (BenchmarkStats) import qualified Cryptol.Utils.Ident as M -- Public Interface ------------------------------------------------------------@@ -63,23 +70,34 @@ findModule n env = runModuleM env (Base.findModule n) -- | Load the module contained in the given file.-loadModuleByPath :: FilePath -> ModuleCmd (ModulePath,T.Module)-loadModuleByPath path minp =- runModuleM minp{ minpModuleEnv = resetModuleEnv (minpModuleEnv minp) } $ do+loadModuleByPath :: FilePath -> ModuleCmd (ModulePath,T.TCTopEntity)+loadModuleByPath path minp = do+ moduleEnv' <- resetModuleEnv $ minpModuleEnv minp+ runModuleM minp{ minpModuleEnv = moduleEnv' } $ do unloadModule ((InFile path ==) . lmFilePath)- m <- Base.loadModuleByPath path- setFocusedModule (T.mName m)+ m <- Base.loadModuleByPath True path+ setFocusedModule (T.tcTopEntitytName m) return (InFile path,m) -- | Load the given parsed module.-loadModuleByName :: P.ModName -> ModuleCmd (ModulePath,T.Module)-loadModuleByName n minp =- runModuleM minp{ minpModuleEnv = resetModuleEnv (minpModuleEnv minp) } $ do+loadModuleByName :: P.ModName -> ModuleCmd (ModulePath,T.TCTopEntity)+loadModuleByName n minp = do+ moduleEnv' <- resetModuleEnv $ minpModuleEnv minp+ runModuleM minp{ minpModuleEnv = moduleEnv' } $ do unloadModule ((n ==) . lmName) (path,m') <- Base.loadModuleFrom False (FromModule n)- setFocusedModule (T.mName m')+ setFocusedModule (T.tcTopEntitytName m') return (path,m') +-- | Parse and typecheck a module, but don't evaluate or change the environment.+checkModuleByPath :: FilePath -> ModuleCmd (ModulePath, T.TCTopEntity)+checkModuleByPath path minp = do+ (res, warns) <- runModuleM minp $ Base.loadModuleByPath False path+ -- restore the old environment+ let res1 = do (x,_newEnv) <- res+ pure ((InFile path, x), minpModuleEnv minp)+ pure (res1, warns)+ -- Extended Environments ------------------------------------------------------- -- These functions are particularly useful for interactive modes, as@@ -95,6 +113,11 @@ evalExpr :: T.Expr -> ModuleCmd Concrete.Value evalExpr e env = runModuleM env (interactive (Base.evalExpr e)) +-- | Benchmark an expression.+benchmarkExpr :: Double -> T.Expr -> ModuleCmd BenchmarkStats+benchmarkExpr period e env =+ runModuleM env (interactive (Base.benchmarkExpr period e))+ -- | Typecheck top-level declarations. checkDecls :: [P.TopDecl PName] -> ModuleCmd (R.NamingEnv,[T.DeclGroup], Map Name T.TySyn) checkDecls ds env = runModuleM env@@ -119,3 +142,16 @@ renameType :: R.NamingEnv -> PName -> ModuleCmd Name renameType names n env = runModuleM env $ interactive $ Base.rename M.interactiveName names (R.renameType R.NameUse n)++--------------------------------------------------------------------------------+-- Dependencies+++-- | Get information about the dependencies of a file.+getFileDependencies :: FilePath -> ModuleCmd (ModulePath, FileInfo)+getFileDependencies f env = runModuleM env (Base.findDepsOf (InFile f))++-- | Get information about the dependencies of a module.+getModuleDependencies :: M.ModName -> ModuleCmd (ModulePath, FileInfo)+getModuleDependencies m env = runModuleM env (Base.findDepsOfModule m)+
src/Cryptol/ModuleSystem/Base.hs view
@@ -11,17 +11,22 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE BlockArguments #-} module Cryptol.ModuleSystem.Base where import qualified Control.Exception as X-import Control.Monad (unless,when)+import Control.Monad (unless,forM)+import Data.Set(Set)+import qualified Data.Set as Set import Data.Maybe (fromMaybe)-import Data.Monoid ((<>))+import Data.List(sortBy,groupBy)+import Data.Function(on)+import Data.Monoid ((<>),Endo(..), Any(..)) import Data.Text.Encoding (decodeUtf8')-import Data.IORef(newIORef,readIORef) import System.Directory (doesFileExist, canonicalizePath) import System.FilePath ( addExtension , isAbsolute@@ -39,39 +44,45 @@ -import Cryptol.ModuleSystem.Env (DynamicEnv(..)) import Cryptol.ModuleSystem.Fingerprint import Cryptol.ModuleSystem.Interface import Cryptol.ModuleSystem.Monad-import Cryptol.ModuleSystem.Name (Name,liftSupply,PrimMap,ModPath(..))-import Cryptol.ModuleSystem.Env (lookupModule- , LoadedModule(..)+import Cryptol.ModuleSystem.Name (Name,liftSupply,PrimMap,ModPath(..),nameIdent)+import Cryptol.ModuleSystem.Env ( DynamicEnv(..),FileInfo(..),fileInfo+ , lookupModule+ , lookupTCEntity+ , LoadedModuleG(..), lmInterface , meCoreLint, CoreLint(..)- , ModContext(..)+ , ModContext(..), ModContextParams(..) , ModulePath(..), modulePathLabel)+import Cryptol.Backend.FFI import qualified Cryptol.Eval as E import qualified Cryptol.Eval.Concrete as Concrete import Cryptol.Eval.Concrete (Concrete(..))+import Cryptol.Eval.FFI import qualified Cryptol.ModuleSystem.NamingEnv as R import qualified Cryptol.ModuleSystem.Renamer as R import qualified Cryptol.Parser as P import qualified Cryptol.Parser.Unlit as P import Cryptol.Parser.AST as P import Cryptol.Parser.NoPat (RemovePatterns(removePatterns))+import qualified Cryptol.Parser.ExpandPropGuards as ExpandPropGuards + ( expandPropGuards, runExpandPropGuardsM ) import Cryptol.Parser.NoInclude (removeIncludesModule) import Cryptol.Parser.Position (HasLoc(..), Range, emptyRange) import qualified Cryptol.TypeCheck as T import qualified Cryptol.TypeCheck.AST as T import qualified Cryptol.TypeCheck.PP as T import qualified Cryptol.TypeCheck.Sanity as TcSanity+import qualified Cryptol.Backend.FFI.Error as FFI -import Cryptol.Transform.AddModParams (addModParams) import Cryptol.Utils.Ident ( preludeName, floatName, arrayName, suiteBName, primeECName , preludeReferenceName, interactiveName, modNameChunks- , notParamInstModName, isParamInstModName )+ , modNameToNormalModName ) import Cryptol.Utils.PP (pretty) import Cryptol.Utils.Panic (panic) import Cryptol.Utils.Logger(logPutStrLn, logPrint)+import Cryptol.Utils.Benchmark import Cryptol.Prelude ( preludeContents, floatContents, arrayContents , suiteBContents, primeECContents, preludeReferenceContents )@@ -114,11 +125,22 @@ unless (null errs) (noPatErrors errs) return a' +-- ExpandPropGuards ------------------------------------------------------------ +-- | Run the expandPropGuards pass.+expandPropGuards :: Module PName -> ModuleM (Module PName)+expandPropGuards a =+ case ExpandPropGuards.runExpandPropGuardsM $ ExpandPropGuards.expandPropGuards a of+ Left err -> expandPropGuardsError err+ Right a' -> pure a'+ -- Parsing --------------------------------------------------------------------- -- | Parse a module and expand includes-parseModule :: ModulePath -> ModuleM (Fingerprint, P.Module PName)+-- Returns a fingerprint of the module, and a set of dependencies due+-- to `include` directives.+parseModule ::+ ModulePath -> ModuleM (Fingerprint, Set FilePath, [P.Module PName]) parseModule path = do getBytes <- getByteReader @@ -150,111 +172,167 @@ } case P.parseModule cfg txt of- Right pm ->+ Right pms -> do let fp = fingerprint bytes- pm1 <- case path of- InFile p ->- do r <- getByteReader- mb <- io (removeIncludesModule r p pm)+ (pm1,deps) <-+ case path of+ InFile p ->+ do r <- getByteReader+ (mo,d) <- unzip <$>+ forM pms \pm ->+ do mb <- io (removeIncludesModule r p pm) case mb of Right ok -> pure ok Left err -> noIncludeErrors err+ pure (mo, Set.unions d) - {- We don't do "include" resolution for in-memory files- because at the moment the include resolution pass requires- the path to the file to be known---this is used when- looking for other inlcude files. This could be- generalized, but we can do it once we have a concrete use- case as it would help guide the design. -}- InMem {} -> pure pm+ {- We don't do "include" resolution for in-memory files+ because at the moment the include resolution pass requires+ the path to the file to be known---this is used when+ looking for other inlcude files. This could be+ generalized, but we can do it once we have a concrete use+ case as it would help guide the design. -}+ InMem {} -> pure (pms, Set.empty) - fp `seq` return (fp, pm1)+{-+ case path of+ InFile {} -> io $ print (T.vcat (map T.pp pm1))+ InMem {} -> pure ()+--}+ fp `seq` return (fp, deps, pm1) Left err -> moduleParseError path err --- Modules ---------------------------------------------------------------------+-- Top Level Modules and Signatures -------------------------------------------- + -- | Load a module by its path.-loadModuleByPath :: FilePath -> ModuleM T.Module-loadModuleByPath path = withPrependedSearchPath [ takeDirectory path ] $ do+loadModuleByPath ::+ Bool {- ^ evaluate declarations in the module -} ->+ FilePath -> ModuleM T.TCTopEntity+loadModuleByPath eval path = withPrependedSearchPath [ takeDirectory path ] $ do let fileName = takeFileName path foundPath <- findFile fileName- (fp, pm) <- parseModule (InFile foundPath)- let n = thing (P.mName pm)+ (fp, deps, pms) <- parseModule (InFile foundPath)+ last <$>+ forM pms \pm ->+ do let n = thing (P.mName pm) - -- Check whether this module name has already been loaded from a different file- env <- getModuleEnv- -- path' is the resolved, absolute path, used only for checking- -- whether it's already been loaded- path' <- io (canonicalizePath foundPath)+ -- Check whether this module name has already been loaded from a+ -- different file+ env <- getModuleEnv+ -- path' is the resolved, absolute path, used only for checking+ -- whether it's already been loaded+ path' <- io (canonicalizePath foundPath) - case lookupModule n env of- -- loadModule will calculate the canonical path again- Nothing -> doLoadModule False (FromModule n) (InFile foundPath) fp pm- Just lm- | path' == loaded -> return (lmModule lm)- | otherwise -> duplicateModuleName n path' loaded- where loaded = lmModuleId lm+ case lookupTCEntity n env of+ -- loadModule will calculate the canonical path again+ Nothing ->+ doLoadModule eval False (FromModule n) (InFile foundPath) fp deps pm+ Just lm+ | path' == loaded -> return (lmData lm)+ | otherwise -> duplicateModuleName n path' loaded+ where loaded = lmModuleId lm -- | Load a module, unless it was previously loaded.-loadModuleFrom :: Bool {- ^ quiet mode -} -> ImportSource -> ModuleM (ModulePath,T.Module)+loadModuleFrom ::+ Bool {- ^ quiet mode -} -> ImportSource -> ModuleM (ModulePath,T.TCTopEntity) loadModuleFrom quiet isrc = do let n = importedModule isrc mb <- getLoadedMaybe n case mb of- Just m -> return (lmFilePath m, lmModule m)+ Just m -> return (lmFilePath m, lmData m) Nothing -> do path <- findModule n errorInFile path $- do (fp, pm) <- parseModule path- m <- doLoadModule quiet isrc path fp pm- return (path,m)+ do (fp, deps, pms) <- parseModule path+ ms <- mapM (doLoadModule True quiet isrc path fp deps) pms+ return (path,last ms) -- | Load dependencies, typecheck, and add to the eval environment. doLoadModule ::+ Bool {- ^ evaluate declarations in the module -} -> Bool {- ^ quiet mode: true suppresses the "loading module" message -} -> ImportSource -> ModulePath -> Fingerprint ->+ Set FilePath {- ^ `include` dependencies -} -> P.Module PName ->- ModuleM T.Module-doLoadModule quiet isrc path fp pm0 =+ ModuleM T.TCTopEntity+doLoadModule eval quiet isrc path fp incDeps pm0 = loading isrc $ do let pm = addPrelude pm0- loadDeps pm+ impDeps <- loadDeps pm + let what = case P.mDef pm of+ P.InterfaceModule {} -> "interface module"+ _ -> "module"+ unless quiet $ withLogger logPutStrLn- ("Loading module " ++ pretty (P.thing (P.mName pm)))+ ("Loading " ++ what ++ " " ++ pretty (P.thing (P.mName pm))) - (nameEnv,tcmod) <- checkModule isrc pm- tcm <- optionalInstantiate tcmod+ (nameEnv,tcm) <- checkModule isrc pm -- extend the eval env, unless a functor. tbl <- Concrete.primTable <$> getEvalOptsAction let ?evalPrim = \i -> Right <$> Map.lookup i tbl callStacks <- getCallStacks let ?callStacks = callStacks- unless (T.isParametrizedModule tcm) $ modifyEvalEnv (E.moduleEnv Concrete tcm)- loadedModule path fp nameEnv tcm+ let shouldEval =+ case tcm of+ T.TCTopModule m | eval && not (T.isParametrizedModule m) -> Just m+ _ -> Nothing + foreignSrc <- case shouldEval of+ Just m ->+ do fsrc <- evalForeign m+ modifyEvalEnv (E.moduleEnv Concrete m)+ pure fsrc+ Nothing -> pure Nothing++ let fi = fileInfo fp incDeps impDeps foreignSrc+ loadedModule path fi nameEnv foreignSrc tcm+ return tcm+ where- optionalInstantiate tcm- | isParamInstModName (importedModule isrc) =- if T.isParametrizedModule tcm then- case addModParams tcm of- Right tcm1 -> return tcm1- Left xs -> failedToParameterizeModDefs (T.mName tcm) xs- else notAParameterizedModule (T.mName tcm)- | otherwise = return tcm+ evalForeign tcm+ | not (null foreignFs) =+ ffiLoadErrors (T.mName tcm) (map FFI.FFIInFunctor foreignFs)+ | not (null dups) =+ ffiLoadErrors (T.mName tcm) (map FFI.FFIDuplicates dups)+ | null foreigns = pure Nothing+ | otherwise =+ case path of+ InFile p -> io (canonicalizePath p >>= loadForeignSrc) >>=+ \case + Right fsrc -> do+ unless quiet $+ case getForeignSrcPath fsrc of+ Just fpath -> withLogger logPutStrLn $+ "Loading dynamic library " ++ takeFileName fpath+ Nothing -> pure ()+ modifyEvalEnvM (evalForeignDecls fsrc foreigns) >>=+ \case+ Right () -> pure $ Just fsrc+ Left errs -> ffiLoadErrors (T.mName tcm) errs + Left err -> ffiLoadErrors (T.mName tcm) [err] + InMem m _ -> panic "doLoadModule"+ ["Can't find foreign source of in-memory module", m] + where foreigns = findForeignDecls tcm+ foreignFs = T.findForeignDeclsInFunctors tcm+ dups = [ d | d@(_ : _ : _) <- groupBy ((==) `on` nameIdent)+ $ sortBy (compare `on` nameIdent)+ $ map fst foreigns ] + -- | Rewrite an import declaration to be of the form: -- -- > import foo as foo [ [hiding] (a,b,c) ]@@ -298,51 +376,149 @@ -- | Discover a file. This is distinct from 'findModule' in that we -- assume we've already been given a particular file name. findFile :: FilePath -> ModuleM FilePath-findFile path | isAbsolute path = do- -- No search path checking for absolute paths- b <- io (doesFileExist path)- if b then return path else cantFindFile path-findFile path = do- paths <- getSearchPath- loop (possibleFiles paths)- where- loop paths = case paths of- path':rest -> do- b <- io (doesFileExist path')- if b then return (normalise path') else loop rest- [] -> cantFindFile path- possibleFiles paths = map (</> path) paths+findFile path+ | isAbsolute path =+ do -- No search path checking for absolute paths+ b <- io (doesFileExist path)+ if b then return path else cantFindFile path+ | otherwise =+ do paths <- getSearchPath+ loop (possibleFiles paths)+ where+ loop paths = case paths of+ path' : rest ->+ do b <- io (doesFileExist path')+ if b then return (normalise path') else loop rest+ [] -> cantFindFile path+ possibleFiles paths = map (</> path) paths -- | Add the prelude to the import list if it's not already mentioned. addPrelude :: P.Module PName -> P.Module PName addPrelude m | preludeName == P.thing (P.mName m) = m | preludeName `elem` importedMods = m- | otherwise = m { mDecls = importPrelude : mDecls m }+ | otherwise = m { mDef = newDef } where+ newDef =+ case mDef m of+ NormalModule ds -> NormalModule (P.DImport prel : ds)+ FunctorInstance f as ins -> FunctorInstance f as ins+ InterfaceModule s -> InterfaceModule s { sigImports = prel+ : sigImports s }+ importedMods = map (P.iModule . P.thing) (P.mImports m)- importPrelude = P.DImport P.Located+ prel = P.Located { P.srcRange = emptyRange , P.thing = P.Import- { iModule = P.ImpTop preludeName- , iAs = Nothing- , iSpec = Nothing+ { iModule = P.ImpTop preludeName+ , iAs = Nothing+ , iSpec = Nothing+ , iInst = Nothing } } -- | Load the dependencies of a module into the environment.-loadDeps :: P.Module name -> ModuleM ()+loadDeps :: P.ModuleG mname name -> ModuleM (Set ModName) loadDeps m =- do mapM_ loadI (P.mImports m)- mapM_ loadF (P.mInstance m)+ do let ds = findDeps m+ mapM_ (loadModuleFrom False) ds+ pure (Set.fromList (map importedModule ds))++-- | Find all imports in a module.+findDeps :: P.ModuleG mname name -> [ImportSource]+findDeps m = appEndo (snd (findDeps' m)) []++findDepsOfModule :: ModName -> ModuleM (ModulePath, FileInfo)+findDepsOfModule m =+ do mpath <- findModule m+ findDepsOf mpath++findDepsOf :: ModulePath -> ModuleM (ModulePath, FileInfo)+findDepsOf mpath' =+ do mpath <- case mpath' of+ InFile file -> InFile <$> io (canonicalizePath file)+ InMem {} -> pure mpath'+ (fp, incs, ms) <- parseModule mpath+ let (anyF,imps) = mconcat (map (findDeps' . addPrelude) ms)+ fpath <- if getAny anyF+ then do mb <- io case mpath of+ InFile can -> foreignLibPath can+ InMem {} -> pure Nothing+ pure case mb of+ Nothing -> Set.empty+ Just f -> Set.singleton f+ else pure Set.empty+ pure+ ( mpath+ , FileInfo+ { fiFingerprint = fp+ , fiIncludeDeps = incs+ , fiImportDeps = Set.fromList (map importedModule (appEndo imps []))+ , fiForeignDeps = fpath+ }+ )++-- | Find the set of top-level modules imported by a module.+findModuleDeps :: P.ModuleG mname name -> Set P.ModName+findModuleDeps = Set.fromList . map importedModule . findDeps++-- | A helper `findDeps` and `findModuleDeps` that actually does the searching.+findDeps' :: P.ModuleG mname name -> (Any, Endo [ImportSource])+findDeps' m =+ case mDef m of+ NormalModule ds -> mconcat (map depsOfDecl ds)+ FunctorInstance f as _ ->+ let fds = loadImpName FromModuleInstance f+ ads = case as of+ DefaultInstArg a -> loadInstArg a+ DefaultInstAnonArg ds -> mconcat (map depsOfDecl ds)+ NamedInstArgs args -> mconcat (map loadNamedInstArg args)+ in fds <> ads+ InterfaceModule s -> mconcat (map loadImpD (sigImports s)) where- loadI i = do (_,m1) <- loadModuleFrom False (FromImport i)- when (T.isParametrizedModule m1) $ importParamModule $ T.mName m1- loadF f = do _ <- loadModuleFrom False (FromModuleInstance f)- return ()+ loadI i = (mempty, Endo (i:)) + loadImpName src l =+ case thing l of+ ImpTop f -> loadI (src l { thing = f })+ _ -> mempty + loadImpD li = loadImpName (FromImport . new) (iModule <$> li)+ where new i = i { thing = (thing li) { iModule = thing i } } + loadNamedInstArg (ModuleInstanceNamedArg _ f) = loadInstArg f+ loadInstArg f =+ case thing f of+ ModuleArg mo -> loadImpName FromModuleInstance f { thing = mo }+ _ -> mempty++ depsOfDecl d =+ case d of+ DImport li -> loadImpD li++ DModule TopLevel { tlValue = NestedModule nm } -> findDeps' nm++ DModParam mo -> loadImpName FromSigImport s+ where s = mpSignature mo++ Decl dd -> depsOfDecl' (tlValue dd)++ _ -> mempty++ depsOfDecl' d =+ case d of+ DLocated d' _ -> depsOfDecl' d'+ DBind b ->+ case thing (bDef b) of+ DForeign {} -> (Any True, mempty)+ _ -> mempty+ _ -> mempty++++++ -- Type Checking --------------------------------------------------------------- -- | Typecheck a single expression, yielding a renamed parsed expression,@@ -405,46 +581,38 @@ Nothing -> panic "Cryptol.ModuleSystem.Base.getPrimMap" [ "Unable to find the prelude" ] --- | Load a module, be it a normal module or a functor instantiation.-checkModule :: ImportSource -> P.Module PName -> ModuleM (R.NamingEnv, T.Module)-checkModule isrc m =- case P.mInstance m of- Nothing -> checkSingleModule T.tcModule isrc m- Just fmName ->- do mbtf <- getLoadedMaybe (thing fmName)- case mbtf of- Just tf ->- do renThis <- io $ newIORef (lmNamingEnv tf)- let how = T.tcModuleInst renThis (lmModule tf)- (_,m') <- checkSingleModule how isrc m- newEnv <- io $ readIORef renThis- pure (newEnv,m')- Nothing -> panic "checkModule"- [ "Functor of module instantiation not loaded" ]----- | Typecheck a single module. If the module is an instantiation--- of a functor, then this just type-checks the instantiating parameters.--- See 'checkModule'+-- | Typecheck a single module. -- Note: we assume that @include@s have already been processed-checkSingleModule ::- Act (P.Module Name) T.Module {- ^ how to check -} ->- ImportSource {- ^ why are we loading this -} ->- P.Module PName {- ^ module to check -} ->- ModuleM (R.NamingEnv,T.Module)-checkSingleModule how isrc m = do+checkModule ::+ ImportSource {- ^ why are we loading this -} ->+ P.Module PName {- ^ module to check -} ->+ ModuleM (R.NamingEnv,T.TCTopEntity)+checkModule isrc m = do -- check that the name of the module matches expectations let nm = importedModule isrc- unless (notParamInstModName nm == thing (P.mName m))+ unless (modNameToNormalModName nm ==+ modNameToNormalModName (thing (P.mName m))) (moduleNameMismatch nm (mName m)) -- remove pattern bindings npm <- noPat m + -- run expandPropGuards+ epgm <- expandPropGuards npm+ -- rename everything- renMod <- renameModule npm+ renMod <- renameModule epgm ++{-+ -- dump renamed+ unless (thing (mName (R.rmModule renMod)) == preludeName)+ do (io $ print (T.pp renMod))+ -- io $ exitSuccess+--}++ -- when generating the prim map for the typechecker, if we're checking the -- prelude, we have to generate the map from the renaming environment, as we -- don't have the interface yet.@@ -453,21 +621,22 @@ else getPrimMap -- typecheck- let act = TCAction { tcAction = how- , tcLinter = moduleLinter (P.thing (P.mName m))+ let act = TCAction { tcAction = T.tcModule+ , tcLinter = tcTopEntitytLinter (P.thing (P.mName m)) , tcPrims = prims } - tcm0 <- typecheck act (R.rmModule renMod) noIfaceParams (R.rmImported renMod)-- let tcm = tcm0 -- fromMaybe tcm0 (addModParams tcm0)+ tcm <- typecheck act (R.rmModule renMod) NoParams (R.rmImported renMod) - rewMod <- liftSupply (`rewModule` tcm)+ rewMod <- case tcm of+ T.TCTopModule mo -> T.TCTopModule <$> liftSupply (`rewModule` mo)+ T.TCTopSignature {} -> pure tcm pure (R.rmInScope renMod,rewMod) data TCLinter o = TCLinter { lintCheck ::- o -> T.InferInput -> Either (Range, TcSanity.Error) [TcSanity.ProofObligation]+ o -> T.InferInput ->+ Either (Range, TcSanity.Error) [TcSanity.ProofObligation] , lintModule :: Maybe P.ModName } @@ -478,7 +647,8 @@ case TcSanity.tcExpr i e' of Left err -> Left err Right (s1,os)- | TcSanity.same s s1 -> Right os+ | TcSanity.SameIf os' <- TcSanity.same s s1 ->+ Right (map T.tMono os' ++ os) | otherwise -> Left ( fromMaybe emptyRange (getLoc e') , TcSanity.TypeMismatch "exprLinter" s s1 )@@ -502,6 +672,17 @@ , lintModule = Just m } +tcTopEntitytLinter :: P.ModName -> TCLinter T.TCTopEntity+tcTopEntitytLinter m = TCLinter+ { lintCheck = \m' i -> case m' of+ T.TCTopModule mo ->+ lintCheck (moduleLinter m) mo i+ T.TCTopSignature {} -> Right []+ -- XXX: what can we lint about module interfaces+ , lintModule = Just m+ }++ type Act i o = i -> T.InferInput -> IO (T.InferOutput o) data TCAction i o = TCAction@@ -511,8 +692,8 @@ } typecheck ::- (Show i, Show o, HasLoc i) => TCAction i o -> i ->- IfaceParams -> IfaceDecls -> ModuleM o+ (Show i, Show o, HasLoc i) =>+ TCAction i o -> i -> ModContextParams -> IfaceDecls -> ModuleM o typecheck act i params env = do let range = fromMaybe emptyRange (getLoc i)@@ -531,8 +712,12 @@ CoreLint -> case lintCheck (tcLinter act) o input of Right as -> let ppIt l = mapM_ (logPrint l . T.pp)- in withLogger ppIt as- Left err -> panic "Core lint failed:" [show err]+ in withLogger ppIt (TcSanity.onlyNonTrivial as)+ Left (loc,err) ->+ panic "Core lint failed:"+ [ "Location: " ++ show (T.pp loc)+ , show (T.pp err)+ ] return o T.InferFailed nameMap warns errs ->@@ -540,8 +725,9 @@ typeCheckingFailed nameMap errs -- | Generate input for the typechecker.-genInferInput :: Range -> PrimMap -> IfaceParams -> IfaceDecls -> ModuleM T.InferInput-genInferInput r prims params env' = do+genInferInput :: Range -> PrimMap -> ModContextParams -> IfaceDecls ->+ ModuleM T.InferInput+genInferInput r prims params env = do seeds <- getNameSeeds monoBinds <- getMonoBinds solver <- getTCSolver@@ -549,25 +735,29 @@ searchPath <- getSearchPath callStacks <- getCallStacks - -- TODO: include the environment needed by the module- let env = flatPublicDecls env'- -- XXX: we should really just pass this directly+ topMods <- getAllLoaded+ topSigs <- getAllLoadedSignatures+ return T.InferInput- { T.inpRange = r- , T.inpVars = Map.map ifDeclSig (ifDecls env)- , T.inpTSyns = ifTySyns env- , T.inpNewtypes = ifNewtypes env- , T.inpAbstractTypes = ifAbstractTypes env- , T.inpNameSeeds = seeds- , T.inpMonoBinds = monoBinds- , T.inpCallStacks = callStacks- , T.inpSearchPath = searchPath- , T.inpSupply = supply- , T.inpPrimNames = prims- , T.inpParamTypes = ifParamTypes params- , T.inpParamConstraints = ifParamConstraints params- , T.inpParamFuns = ifParamFuns params+ { T.inpRange = r+ , T.inpVars = Map.map ifDeclSig (ifDecls env)+ , T.inpTSyns = ifTySyns env+ , T.inpNewtypes = ifNewtypes env+ , T.inpAbstractTypes = ifAbstractTypes env+ , T.inpSignatures = ifSignatures env+ , T.inpNameSeeds = seeds+ , T.inpMonoBinds = monoBinds+ , T.inpCallStacks = callStacks+ , T.inpSearchPath = searchPath+ , T.inpSupply = supply+ , T.inpParams = case params of+ NoParams -> T.allParamNames mempty+ FunctorParams ps -> T.allParamNames ps+ InterfaceParams ps -> ps+ , T.inpPrimNames = prims , T.inpSolver = solver+ , T.inpTopModules = topMods+ , T.inpTopSignatures = topSigs } @@ -585,6 +775,22 @@ let ?callStacks = callStacks io $ E.runEval mempty (E.evalExpr Concrete (env <> deEnv denv) e)++benchmarkExpr :: Double -> T.Expr -> ModuleM BenchmarkStats+benchmarkExpr period e = do+ env <- getEvalEnv+ denv <- getDynEnv+ evopts <- getEvalOptsAction+ let env' = env <> deEnv denv+ let tbl = Concrete.primTable evopts+ let ?evalPrim = \i -> Right <$> Map.lookup i tbl+ let ?range = emptyRange+ callStacks <- getCallStacks+ let ?callStacks = callStacks++ let eval expr = E.runEval mempty $+ E.evalExpr Concrete env' expr >>= E.forceValue+ io $ benchmark period eval e evalDecls :: [T.DeclGroup] -> ModuleM () evalDecls dgs = do
+ src/Cryptol/ModuleSystem/Binds.hs view
@@ -0,0 +1,434 @@+{-# Language BlockArguments #-}+{-# Language RecordWildCards #-}+{-# Language FlexibleInstances #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+module Cryptol.ModuleSystem.Binds+ ( BindsNames+ , TopDef(..)+ , Mod(..)+ , ModKind(..)+ , modNested+ , modBuilder+ , topModuleDefs+ , topDeclsDefs+ , newModParam+ , InModule(..)+ , ifaceToMod+ , ifaceSigToMod+ , modToMap+ , defsOf+ ) where++import Data.Map(Map)+import qualified Data.Map as Map+import Data.Set(Set)+import qualified Data.Set as Set+import Data.Maybe(fromMaybe)+import Control.Monad(foldM)+import qualified MonadLib as M++import Cryptol.Utils.Panic (panic)+import Cryptol.Utils.Ident(allNamespaces)+import Cryptol.Parser.Position+import Cryptol.Parser.Name(isGeneratedName)+import Cryptol.Parser.AST+import Cryptol.ModuleSystem.Exports(exportedDecls,exported)+import Cryptol.ModuleSystem.Renamer.Error+import Cryptol.ModuleSystem.Name+import Cryptol.ModuleSystem.Names+import Cryptol.ModuleSystem.NamingEnv+import Cryptol.ModuleSystem.Interface+import Cryptol.TypeCheck.Type(ModParamNames(..))++++data TopDef = TopMod ModName (Mod ())+ | TopInst ModName (ImpName PName) (ModuleInstanceArgs PName)++-- | Things defined by a module+data Mod a = Mod+ { modImports :: [ ImportG (ImpName PName) ]+ , modKind :: ModKind+ , modInstances :: Map Name (ImpName PName, ModuleInstanceArgs PName)+ , modMods :: Map Name (Mod a) -- ^ this includes signatures++ , modDefines :: NamingEnv+ {- ^ Things defined by this module. Note the for normal modules we+ really just need the public names, however for things within+ functors we need all defined names, so that we can generate fresh+ names in instantiations -}++ , modPublic :: !(Set Name)+ -- ^ These are the exported names++ , modState :: a+ {- ^ Used in the import loop to track the current state of processing.+ The reason this is here, rather than just having a pair in the+ other algorithm is because this type is recursive (for nested modules)+ and it is conveninet to keep track for all modules at once -}+ }++modNested :: Mod a -> Set Name+modNested m = Set.unions [ Map.keysSet (modInstances m)+ , Map.keysSet (modMods m)+ ]++instance Functor Mod where+ fmap f m = m { modState = f (modState m)+ , modMods = fmap f <$> modMods m+ }++-- | Generate a map from this module and all modules nested in it.+modToMap ::+ ImpName Name -> Mod () ->+ Map (ImpName Name) (Mod ()) -> Map (ImpName Name) (Mod ())+modToMap x m mp = Map.insert x m (Map.foldrWithKey add mp (modMods m))+ where+ add n = modToMap (ImpNested n)++-- | Make a `Mod` from the public declarations in an interface.+-- This is used to handle imports.+ifaceToMod :: IfaceG name -> Mod ()+ifaceToMod iface = ifaceNamesToMod iface (ifaceIsFunctor iface) (ifNames iface)++ifaceNamesToMod :: IfaceG topname -> Bool -> IfaceNames name -> Mod ()+ifaceNamesToMod iface params names =+ Mod+ { modKind = if params then AFunctor else AModule+ , modMods = (ifaceNamesToMod iface False <$> ifModules decls)+ `Map.union`+ (ifaceToMod <$> ifFunctors decls)+ `Map.union`+ (ifaceSigToMod <$> ifSignatures decls)+ , modDefines = namingEnvFromNames defs+ , modPublic = ifsPublic names++ , modImports = []+ , modInstances = mempty+ , modState = ()+ }+ where+ defs = ifsDefines names+ isLocal x = x `Set.member` defs+ decls = filterIfaceDecls isLocal (ifDefines iface)+++ifaceSigToMod :: ModParamNames -> Mod ()+ifaceSigToMod ps = Mod+ { modImports = []+ , modKind = ASignature+ , modInstances = mempty+ , modMods = mempty+ , modDefines = env+ , modPublic = namingEnvNames env+ , modState = ()+ }+ where+ env = modParamsNamingEnv ps+++++++type ModBuilder = SupplyT (M.StateT [RenamerError] M.Id)++modBuilder :: ModBuilder a -> Supply -> ((a, [RenamerError]),Supply)+modBuilder m s = ((a,errs),s1)+ where ((a,s1),errs) = M.runId (M.runStateT [] (runSupplyT s m))++defErr :: RenamerError -> ModBuilder ()+defErr a = M.lift (M.sets_ (a:))++defNames :: BuildNamingEnv -> ModBuilder NamingEnv+defNames b = liftSupply \s -> M.runId (runSupplyT s (runBuild b))+++topModuleDefs :: Module PName -> ModBuilder TopDef+topModuleDefs m =+ case mDef m of+ NormalModule ds -> TopMod mname <$> declsToMod (Just (TopModule mname)) ds+ FunctorInstance f as _ -> pure (TopInst mname (thing f) as)+ InterfaceModule s -> TopMod mname <$> sigToMod (TopModule mname) s+ where+ mname = thing (mName m)++topDeclsDefs :: ModPath -> [TopDecl PName] -> ModBuilder (Mod ())+topDeclsDefs = declsToMod . Just++sigToMod :: ModPath -> Signature PName -> ModBuilder (Mod ())+sigToMod mp sig =+ do env <- defNames (signatureDefs mp sig)+ pure Mod { modImports = map thing (sigImports sig)+ , modKind = ASignature+ , modInstances = mempty+ , modMods = mempty+ , modDefines = env+ , modPublic = namingEnvNames env+ , modState = ()+ }++++declsToMod :: Maybe ModPath -> [TopDecl PName] -> ModBuilder (Mod ())+declsToMod mbPath ds =+ do defs <- defNames (foldMap (namingEnv . InModule mbPath) ds)+ let expSpec = exportedDecls ds+ let pub = Set.fromList+ [ name+ | ns <- allNamespaces+ , pname <- Set.toList (exported ns expSpec)+ , name <- lookupListNS ns pname defs+ ]++ case findAmbig defs of+ bad@(_ : _) : _ ->+ -- defErr (MultipleDefinitions mbPath (nameIdent f) (map nameLoc bad))+ defErr (OverlappingSyms bad)+ _ -> pure ()++ let mo = Mod { modImports = [ thing i | DImport i <- ds ]+ , modKind = if any isParamDecl ds+ then AFunctor else AModule+ , modInstances = mempty+ , modMods = mempty+ , modDefines = defs+ , modPublic = pub+ , modState = ()+ }++ foldM (checkNest defs) mo ds++ where+ checkNest defs mo d =+ case d of+ DModule tl ->+ do let NestedModule nmod = tlValue tl+ pname = thing (mName nmod)+ name = case lookupNS NSModule pname defs of+ Just xs -> anyOne xs+ _ -> panic "declsToMod" ["undefined name", show pname]+ case mbPath of+ Nothing ->+ do defErr (UnexpectedNest (srcRange (mName nmod)) pname)+ pure mo+ Just path ->+ case mDef nmod of++ NormalModule xs ->+ do m <- declsToMod (Just (Nested path (nameIdent name))) xs+ pure mo { modMods = Map.insert name m (modMods mo) }++ FunctorInstance f args _ ->+ pure mo { modInstances = Map.insert name (thing f, args)+ (modInstances mo) }++ InterfaceModule sig ->+ do m <- sigToMod (Nested path (nameIdent name)) sig+ pure mo { modMods = Map.insert name m (modMods mo) }+++ _ -> pure mo++++-- | These are the names "owned" by the signature. These names are+-- used when resolving the signature. They are also used to figure out what+-- names to instantuate when the signature is used.+signatureDefs :: ModPath -> Signature PName -> BuildNamingEnv+signatureDefs m sig =+ mconcat [ namingEnv (InModule loc p) | p <- sigTypeParams sig ]+ <> mconcat [ namingEnv (InModule loc p) | p <- sigFunParams sig ]+ <> mconcat [ namingEnv (InModule loc p) | p <- sigDecls sig ]+ where+ loc = Just m+--------------------------------------------------------------------------------+++++--------------------------------------------------------------------------------+-- Computes the names introduced by various declarations.++-- | Things that define exported names.+class BindsNames a where+ namingEnv :: a -> BuildNamingEnv++newtype BuildNamingEnv = BuildNamingEnv { runBuild :: SupplyT M.Id NamingEnv }++buildNamingEnv :: BuildNamingEnv -> Supply -> (NamingEnv,Supply)+buildNamingEnv b supply = M.runId $ runSupplyT supply $ runBuild b++-- | Generate a 'NamingEnv' using an explicit supply.+defsOf :: BindsNames a => a -> Supply -> (NamingEnv,Supply)+defsOf = buildNamingEnv . namingEnv++instance Semigroup BuildNamingEnv where+ BuildNamingEnv a <> BuildNamingEnv b = BuildNamingEnv $+ do x <- a+ y <- b+ return (mappend x y)++instance Monoid BuildNamingEnv where+ mempty = BuildNamingEnv (pure mempty)++ mappend = (<>)++ mconcat bs = BuildNamingEnv $+ do ns <- sequence (map runBuild bs)+ return (mconcat ns)++instance BindsNames NamingEnv where+ namingEnv env = BuildNamingEnv (return env)+ {-# INLINE namingEnv #-}++instance BindsNames a => BindsNames (Maybe a) where+ namingEnv = foldMap namingEnv+ {-# INLINE namingEnv #-}++instance BindsNames a => BindsNames [a] where+ namingEnv = foldMap namingEnv+ {-# INLINE namingEnv #-}++-- | Generate a type renaming environment from the parameters that are bound by+-- this schema.+instance BindsNames (Schema PName) where+ namingEnv (Forall ps _ _ _) = foldMap namingEnv ps+ {-# INLINE namingEnv #-}++++-- | Introduce the name+instance BindsNames (InModule (Bind PName)) where+ namingEnv (InModule mb b) = BuildNamingEnv $+ do let Located { .. } = bName b+ n <- case mb of+ Just m -> newTop NSValue m thing (bFixity b) srcRange+ Nothing -> newLocal NSValue thing srcRange -- local fixitiies?++ return (singletonNS NSValue thing n)++-- | Generate the naming environment for a type parameter.+instance BindsNames (TParam PName) where+ namingEnv TParam { .. } = BuildNamingEnv $+ do let range = fromMaybe emptyRange tpRange+ n <- newLocal NSType tpName range+ return (singletonNS NSType tpName n)+++instance BindsNames (InModule (TopDecl PName)) where+ namingEnv (InModule ns td) =+ case td of+ Decl d -> namingEnv (InModule ns (tlValue d))+ DPrimType d -> namingEnv (InModule ns (tlValue d))+ TDNewtype d -> namingEnv (InModule ns (tlValue d))+ DParamDecl {} -> mempty+ Include _ -> mempty+ DImport {} -> mempty -- see 'openLoop' in the renamer+ DModule m -> namingEnv (InModule ns (tlValue m))+ DModParam {} -> mempty -- shouldn't happen+ DInterfaceConstraint {} -> mempty+ -- handled in the renamer as we need to resolve+ -- the signature name first (similar to import)+++instance BindsNames (InModule (NestedModule PName)) where+ namingEnv (InModule ~(Just m) (NestedModule mdef)) = BuildNamingEnv $+ 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 { .. }) =+ 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 $+ 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 $+ -- 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 $+ do let Located { .. } = nName+ ntName <- newTop NSType ns thing Nothing srcRange+ ntConName <- newTop NSValue ns thing Nothing srcRange+ return (singletonNS NSType thing ntName `mappend`+ singletonNS NSValue thing ntConName)++-- | The naming environment for a single declaration.+instance BindsNames (InModule (Decl PName)) where+ namingEnv (InModule pfx d) = case d of+ DBind b -> namingEnv (InModule pfx b)+ DSignature ns _sig -> foldMap qualBind ns+ DPragma ns _p -> foldMap qualBind ns+ DType syn -> qualType (tsName syn) (tsFixity syn)+ DProp syn -> qualType (psName syn) (psFixity syn)+ DLocated d' _ -> namingEnv (InModule pfx d')+ DRec {} -> panic "namingEnv" [ "DRec" ]+ DPatBind _pat _e -> panic "namingEnv" ["Unexpected pattern binding"]+ DFixity{} -> panic "namingEnv" ["Unexpected fixity declaration"]++ where++ mkName ns ln fx = case pfx of+ Just m -> newTop ns m (thing ln) fx (srcRange ln)+ Nothing -> newLocal ns (thing ln) (srcRange ln)++ qualBind ln = BuildNamingEnv $+ do n <- mkName NSValue ln Nothing+ return (singletonNS NSValue (thing ln) n)++ qualType ln f = BuildNamingEnv $+ do n <- mkName NSType ln f+ return (singletonNS NSType (thing ln) n)++instance BindsNames (InModule (SigDecl PName)) where+ namingEnv (InModule m d) =+ case d of+ SigTySyn ts _ -> namingEnv (InModule m (DType ts))+ SigPropSyn ps _ -> namingEnv (InModule m (DProp ps))+++++--------------------------------------------------------------------------------+-- Helpers++newTop ::+ FreshM m => Namespace -> ModPath -> PName -> Maybe Fixity -> Range -> m Name+newTop ns m thing fx rng =+ liftSupply (mkDeclared ns m src (getIdent thing) fx rng)+ where src = if isGeneratedName thing then SystemName else UserName++newLocal :: FreshM m => Namespace -> PName -> Range -> m Name+newLocal ns thing rng = liftSupply (mkLocal ns (getIdent thing) rng)++-- | Given a name in a signature, make a name for the parameter corresponding+-- to the signature.+newModParam :: FreshM m => ModPath -> Ident -> Range -> Name -> m Name+newModParam m i rng n = liftSupply (mkModParam m i rng n)+++{- | Do something in the context of a module.+If `Nothing` than we are working with a local declaration.+Otherwise we are at the top-level of the given module.++By wrapping types with this, we can pass the module path+to methods that need the extra information. -}+data InModule a = InModule (Maybe ModPath) a+ deriving (Functor,Traversable,Foldable,Show)+++
src/Cryptol/ModuleSystem/Env.hs view
@@ -7,17 +7,20 @@ -- Portability : portable {-# LANGUAGE CPP #-}+{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-} module Cryptol.ModuleSystem.Env where #ifndef RELOCATABLE import Paths_cryptol (getDataDir) #endif +import Cryptol.Backend.FFI (ForeignSrc, unloadForeignSrc, getForeignSrcPath) import Cryptol.Eval (EvalEnv) import Cryptol.ModuleSystem.Fingerprint import Cryptol.ModuleSystem.Interface@@ -34,13 +37,16 @@ import qualified Control.Exception as X import Data.Function (on) import Data.Set(Set)+import qualified Data.Set as Set import Data.Map (Map) import qualified Data.Map as Map import Data.Semigroup+import Data.Maybe(fromMaybe) import System.Directory (getAppUserDataDirectory, getCurrentDirectory) import System.Environment(getExecutablePath) import System.FilePath ((</>), normalise, joinPath, splitPath, takeDirectory) import qualified Data.List as List+import Data.Foldable import GHC.Generics (Generic) import Control.DeepSeq@@ -99,14 +105,19 @@ | CoreLint -- ^ Run core lint deriving (Generic, NFData) -resetModuleEnv :: ModuleEnv -> ModuleEnv-resetModuleEnv env = env- { meLoadedModules = mempty- , meNameSeeds = T.nameSeeds- , meEvalEnv = mempty- , meFocusedModule = Nothing- , meDynEnv = mempty- }+resetModuleEnv :: ModuleEnv -> IO ModuleEnv+resetModuleEnv env = do+ for_ (getLoadedModules $ meLoadedModules env) $ \lm ->+ case lmForeignSrc (lmData lm) of+ Just fsrc -> unloadForeignSrc fsrc+ _ -> pure ()+ pure env+ { meLoadedModules = mempty+ , meNameSeeds = T.nameSeeds+ , meEvalEnv = mempty+ , meFocusedModule = Nothing+ , meDynEnv = mempty+ } initialModuleEnv :: IO ModuleEnv initialModuleEnv = do@@ -171,9 +182,9 @@ loadedNonParamModules :: ModuleEnv -> [T.Module] loadedNonParamModules = map lmModule . lmLoadedModules . meLoadedModules -loadedNewtypes :: ModuleEnv -> Map Name IfaceNewtype+loadedNewtypes :: ModuleEnv -> Map Name T.Newtype loadedNewtypes menv = Map.unions- [ ifNewtypes (ifPublic i) <> ifNewtypes (ifPrivate i)+ [ ifNewtypes (ifDefines i) <> ifNewtypes (ifDefines i) | i <- map lmInterface (getLoadedModules (meLoadedModules menv)) ] @@ -184,10 +195,22 @@ allDeclGroups :: ModuleEnv -> [T.DeclGroup] allDeclGroups = concatMap T.mDecls . loadedNonParamModules +data ModContextParams =+ InterfaceParams T.ModParamNames+ | FunctorParams T.FunctorParams+ | NoParams++modContextParamNames :: ModContextParams -> T.ModParamNames+modContextParamNames mp =+ case mp of+ InterfaceParams ps -> ps+ FunctorParams ps -> T.allParamNames ps+ NoParams -> T.allParamNames mempty+ -- | Contains enough information to browse what's in scope, -- or type check new expressions. data ModContext = ModContext- { mctxParams :: IfaceParams+ { mctxParams :: ModContextParams -- T.FunctorParams , mctxExported :: Set Name , mctxDecls :: IfaceDecls -- ^ Should contain at least names in NamingEnv, but may have more@@ -199,7 +222,7 @@ -- This instance is a bit bogus. It is mostly used to add the dynamic -- environemnt to an existing module, and it makes sense for that use case. instance Semigroup ModContext where- x <> y = ModContext { mctxParams = jnParams (mctxParams x) (mctxParams y)+ x <> y = ModContext { mctxParams = jnPs (mctxParams x) (mctxParams y) , mctxExported = mctxExported x <> mctxExported y , mctxDecls = mctxDecls x <> mctxDecls y , mctxNames = names@@ -208,14 +231,15 @@ where names = mctxNames x `R.shadowing` mctxNames y- jnParams a b- | isEmptyIfaceParams a = b- | isEmptyIfaceParams b = a- | otherwise =- panic "ModContext" [ "Cannot combined 2 parameterized contexts" ]+ jnPs as bs =+ case (as,bs) of+ (NoParams,_) -> bs+ (_,NoParams) -> as+ (FunctorParams xs, FunctorParams ys) -> FunctorParams (xs <> ys)+ _ -> panic "(<>) @ ModContext" ["Can't combine parameters"] instance Monoid ModContext where- mempty = ModContext { mctxParams = noIfaceParams+ mempty = ModContext { mctxParams = NoParams , mctxDecls = mempty , mctxExported = mempty , mctxNames = mempty@@ -229,16 +253,36 @@ do lm <- lookupModule mname me let localIface = lmInterface lm localNames = lmNamingEnv lm- loadedDecls = map (ifPublic . lmInterface)++ -- XXX: do we want only public ones here?+ loadedDecls = map (ifDefines . lmInterface) $ getLoadedModules (meLoadedModules me)++ params = ifParams localIface pure ModContext- { mctxParams = ifParams localIface- , mctxExported = ifaceDeclsNames (ifPublic localIface)- , mctxDecls = mconcat (ifPrivate localIface : loadedDecls)+ { mctxParams = if Map.null params then NoParams+ else FunctorParams params+ , mctxExported = ifsPublic (ifNames localIface)+ , mctxDecls = mconcat (ifDefines localIface : loadedDecls) , mctxNames = localNames , mctxNameDisp = R.toNameDisp localNames }+ `mplus`+ do lm <- lookupSignature mname me+ let localNames = lmNamingEnv lm+ -- XXX: do we want only public ones here?+ loadedDecls = map (ifDefines . lmInterface)+ $ getLoadedModules (meLoadedModules me)+ pure ModContext+ { mctxParams = InterfaceParams (lmData lm)+ , mctxExported = Set.empty+ , mctxDecls = mconcat loadedDecls+ , mctxNames = localNames+ , mctxNameDisp = R.toNameDisp localNames+ } ++ dynModContext :: ModuleEnv -> ModContext dynModContext me = mempty { mctxNames = dynNames , mctxNameDisp = R.toNameDisp dynNames@@ -277,6 +321,17 @@ (InMem a _, InMem b _) -> a == b _ -> False +-- | In-memory things are compared by label.+instance Ord ModulePath where+ compare p1 p2 =+ case (p1,p2) of+ (InFile x, InFile y) -> compare x y+ (InMem a _, InMem b _) -> compare a b+ (InMem {}, InFile {}) -> LT+ (InFile {}, InMem {}) -> GT+++ instance PP ModulePath where ppPrec _ e = case e of@@ -303,24 +358,49 @@ , lmLoadedParamModules :: [LoadedModule] -- ^ Loaded parameterized modules. + , lmLoadedSignatures :: ![LoadedSignature]+ } deriving (Show, Generic, NFData) +data LoadedEntity =+ ALoadedModule LoadedModule+ | ALoadedFunctor LoadedModule+ | ALoadedInterface LoadedSignature++getLoadedEntities ::+ LoadedModules -> Map ModName LoadedEntity+getLoadedEntities lm =+ Map.fromList $ [ (lmName x, ALoadedModule x) | x <- lmLoadedModules lm ] +++ [ (lmName x, ALoadedFunctor x) | x <- lmLoadedParamModules lm ] +++ [ (lmName x, ALoadedInterface x) | x <- lmLoadedSignatures lm ]+ getLoadedModules :: LoadedModules -> [LoadedModule] getLoadedModules x = lmLoadedParamModules x ++ lmLoadedModules x +getLoadedNames :: LoadedModules -> Set ModName+getLoadedNames lm = Set.fromList+ $ map lmName (lmLoadedModules lm)+ ++ map lmName (lmLoadedParamModules lm)+ ++ map lmName (lmLoadedSignatures lm)+ instance Semigroup LoadedModules where l <> r = LoadedModules { lmLoadedModules = List.unionBy ((==) `on` lmName) (lmLoadedModules l) (lmLoadedModules r)- , lmLoadedParamModules = lmLoadedParamModules l ++ lmLoadedParamModules r }+ , lmLoadedParamModules = lmLoadedParamModules l ++ lmLoadedParamModules r+ , lmLoadedSignatures = lmLoadedSignatures l ++ lmLoadedSignatures r+ } instance Monoid LoadedModules where mempty = LoadedModules { lmLoadedModules = [] , lmLoadedParamModules = []+ , lmLoadedSignatures = [] } mappend = (<>) -data LoadedModule = LoadedModule+-- | A generic type for loaded things.+-- The things can be either modules or signatures.+data LoadedModuleG a = LoadedModule { lmName :: ModName -- ^ The name of this module. Should match what's in 'lmModule' @@ -335,36 +415,94 @@ , lmNamingEnv :: !R.NamingEnv -- ^ What's in scope in this module - , lmInterface :: Iface+ , lmFileInfo :: !FileInfo++ , lmData :: a+ } deriving (Show, Generic, NFData)++type LoadedModule = LoadedModuleG LoadedModuleData++lmModule :: LoadedModule -> T.Module+lmModule = lmdModule . lmData++lmInterface :: LoadedModule -> Iface+lmInterface = lmdInterface . lmData++data LoadedModuleData = LoadedModuleData+ { lmdInterface :: Iface -- ^ The module's interface. - , lmModule :: T.Module+ , lmdModule :: T.Module -- ^ The actual type-checked module - , lmFingerprint :: Fingerprint+ , lmForeignSrc :: Maybe ForeignSrc+ -- ^ The dynamically loaded source for any foreign functions in the module } deriving (Show, Generic, NFData) +type LoadedSignature = LoadedModuleG T.ModParamNames++ -- | Has this module been loaded already. isLoaded :: ModName -> LoadedModules -> Bool-isLoaded mn lm = any ((mn ==) . lmName) (getLoadedModules lm)+isLoaded mn lm = mn `Set.member` getLoadedNames lm -- | Is this a loaded parameterized module. isLoadedParamMod :: ModName -> LoadedModules -> Bool isLoadedParamMod mn ln = any ((mn ==) . lmName) (lmLoadedParamModules ln) +-- | Is this a loaded interface module.+isLoadedInterface :: ModName -> LoadedModules -> Bool+isLoadedInterface mn ln = any ((mn ==) . lmName) (lmLoadedSignatures ln)++++lookupTCEntity :: ModName -> ModuleEnv -> Maybe (LoadedModuleG T.TCTopEntity)+lookupTCEntity m env =+ case lookupModule m env of+ Just lm -> pure lm { lmData = T.TCTopModule (lmModule lm) }+ Nothing ->+ do lm <- lookupSignature m env+ pure lm { lmData = T.TCTopSignature m (lmData lm) }+ -- | Try to find a previously loaded module lookupModule :: ModName -> ModuleEnv -> Maybe LoadedModule lookupModule mn me = search lmLoadedModules `mplus` search lmLoadedParamModules where search how = List.find ((mn ==) . lmName) (how (meLoadedModules me)) +lookupSignature :: ModName -> ModuleEnv -> Maybe LoadedSignature+lookupSignature mn me =+ List.find ((mn ==) . lmName) (lmLoadedSignatures (meLoadedModules me)) +addLoadedSignature ::+ ModulePath -> String ->+ FileInfo ->+ R.NamingEnv ->+ ModName -> T.ModParamNames ->+ LoadedModules -> LoadedModules+addLoadedSignature path ident fi nameEnv nm si lm+ | isLoaded nm lm = lm+ | otherwise = lm { lmLoadedSignatures = loaded : lmLoadedSignatures lm }+ where+ loaded = LoadedModule+ { lmName = nm+ , lmFilePath = path+ , lmModuleId = ident+ , lmNamingEnv = nameEnv+ , lmData = si+ , lmFileInfo = fi+ }+ -- | Add a freshly loaded module. If it was previously loaded, then -- the new version is ignored. addLoadedModule ::- ModulePath -> String -> Fingerprint -> R.NamingEnv -> T.Module ->- LoadedModules -> LoadedModules-addLoadedModule path ident fp nameEnv tm lm+ ModulePath ->+ String ->+ FileInfo ->+ R.NamingEnv ->+ Maybe ForeignSrc ->+ T.Module -> LoadedModules -> LoadedModules+addLoadedModule path ident fi nameEnv fsrc tm lm | isLoaded (T.mName tm) lm = lm | T.isParametrizedModule tm = lm { lmLoadedParamModules = loaded : lmLoadedParamModules lm }@@ -376,21 +514,53 @@ , lmFilePath = path , lmModuleId = ident , lmNamingEnv = nameEnv- , lmInterface = T.genIface tm- , lmModule = tm- , lmFingerprint = fp+ , lmData = LoadedModuleData+ { lmdInterface = T.genIface tm+ , lmdModule = tm+ , lmForeignSrc = fsrc+ }+ , lmFileInfo = fi } -- | Remove a previously loaded module. -- Note that this removes exactly the modules specified by the predicate. -- One should be carfule to preserve the invariant on 'LoadedModules'.-removeLoadedModule :: (LoadedModule -> Bool) -> LoadedModules -> LoadedModules+removeLoadedModule ::+ (forall a. LoadedModuleG a -> Bool) -> LoadedModules -> LoadedModules removeLoadedModule rm lm = LoadedModules- { lmLoadedModules = filter (not . rm) (lmLoadedModules lm)- , lmLoadedParamModules = filter (not . rm) (lmLoadedParamModules lm)+ { lmLoadedModules = filter (not . rm) (lmLoadedModules lm)+ , lmLoadedParamModules = filter (not . rm) (lmLoadedParamModules lm)+ , lmLoadedSignatures = filter (not . rm) (lmLoadedSignatures lm) } +-- FileInfo --------------------------------------------------------------------++data FileInfo = FileInfo+ { fiFingerprint :: Fingerprint+ , fiIncludeDeps :: Set FilePath+ , fiImportDeps :: Set ModName+ , fiForeignDeps :: Set FilePath+ } deriving (Show,Generic,NFData)+++fileInfo ::+ Fingerprint ->+ Set FilePath ->+ Set ModName ->+ Maybe ForeignSrc ->+ FileInfo+fileInfo fp incDeps impDeps fsrc =+ FileInfo+ { fiFingerprint = fp+ , fiIncludeDeps = incDeps+ , fiImportDeps = impDeps+ , fiForeignDeps = fromMaybe Set.empty+ do src <- fsrc+ Set.singleton <$> getForeignSrcPath src+ }++ -- Dynamic Environments -------------------------------------------------------- -- | Extra information we need to carry around to dynamically extend@@ -433,6 +603,8 @@ , ifAbstractTypes = Map.empty , ifDecls = decls , ifModules = Map.empty+ , ifFunctors = Map.empty+ , ifSignatures = Map.empty } where decls = mconcat
src/Cryptol/ModuleSystem/Exports.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE Safe #-} module Cryptol.ModuleSystem.Exports where import Data.Set(Set)@@ -10,30 +11,32 @@ import GHC.Generics (Generic) import Cryptol.Parser.AST-import Cryptol.Parser.Names(namesD,tnamesD,tnamesNT)+import Cryptol.Parser.Names(namesD,tnamesD,namesNT,tnamesNT) import Cryptol.ModuleSystem.Name -modExports :: Ord name => ModuleG mname name -> ExportSpec name-modExports m = fold (concat [ exportedNames d | d <- mDecls m ])-+exportedDecls :: Ord name => [TopDecl name] -> ExportSpec name+exportedDecls ds = fold (concat [ exportedNames d | d <- ds ]) exportedNames :: Ord name => TopDecl name -> [ExportSpec name]-exportedNames (Decl td) = map exportBind (names namesD td)- ++ map exportType (names tnamesD td)-exportedNames (DPrimType t) = [ exportType (thing . primTName <$> t) ]-exportedNames (TDNewtype nt) = map exportType (names tnamesNT nt)-exportedNames (Include {}) = []-exportedNames (DImport {}) = []-exportedNames (DParameterFun {}) = []-exportedNames (DParameterType {}) = []-exportedNames (DParameterConstraint {}) = []-exportedNames (DModule nested) =- case tlValue nested of- NestedModule x ->- [exportName NSModule nested { tlValue = thing (mName x) }]+exportedNames decl =+ case decl of+ Decl td -> map exportBind (names namesD td)+ ++ map exportType (names tnamesD td)+ DPrimType t -> [ exportType (thing . primTName <$> t) ]+ TDNewtype nt -> map exportType (names tnamesNT nt) +++ map exportBind (names namesNT nt)+ Include {} -> []+ DImport {} -> []+ DParamDecl {} -> []+ DInterfaceConstraint {} -> []+ DModule nested ->+ case tlValue nested of+ NestedModule x ->+ [exportName NSModule nested { tlValue = thing (mName x) }]+ DModParam {} -> []+ where+ names by td = [ td { tlValue = thing n } | n <- fst (by (tlValue td)) ] -names :: (a -> ([Located a'], b)) -> TopLevel a -> [TopLevel a']-names by td = [ td { tlValue = thing n } | n <- fst (by (tlValue td)) ] newtype ExportSpec name = ExportSpec (Map Namespace (Set name))@@ -53,6 +56,9 @@ $ Map.singleton ns $ Set.singleton (tlValue n) | otherwise = mempty++allExported :: Ord name => ExportSpec name -> Set name+allExported (ExportSpec mp) = Set.unions (Map.elems mp) exported :: Namespace -> ExportSpec name -> Set name exported ns (ExportSpec mp) = Map.findWithDefault Set.empty ns mp
src/Cryptol/ModuleSystem/Fingerprint.hs view
@@ -10,6 +10,7 @@ ( Fingerprint , fingerprint , fingerprintFile+ , fingerprintHexString ) where import Control.DeepSeq (NFData (rnf))@@ -17,6 +18,7 @@ import Data.ByteString (ByteString) import Control.Exception (try) import qualified Data.ByteString as B+import qualified Data.Vector as Vector newtype Fingerprint = Fingerprint ByteString deriving (Eq, Show)@@ -37,3 +39,13 @@ case res :: Either IOError ByteString of Left{} -> Nothing Right b -> Just $! fingerprint b++fingerprintHexString :: Fingerprint -> String+fingerprintHexString (Fingerprint bs) = B.foldr hex "" bs+ where+ digits = Vector.fromList "0123456789ABCDEF"+ digit x = digits Vector.! fromIntegral x+ hex b cs = let (x,y) = divMod b 16+ in digit x : digit y : cs++
− src/Cryptol/ModuleSystem/InstantiateModule.hs
@@ -1,325 +0,0 @@-{-# Language FlexibleInstances, PatternGuards #-}-{-# Language BlockArguments #-}--- | Assumes that local names do not shadow top level names.-module Cryptol.ModuleSystem.InstantiateModule- ( instantiateModule- ) where--import Data.Set (Set)-import qualified Data.Set as Set-import Data.Map (Map)-import qualified Data.Map as Map-import MonadLib(ReaderT,runReaderT,ask)--import Cryptol.Utils.Panic(panic)-import Cryptol.Utils.Ident(ModName,modParamIdent)-import Cryptol.Parser.Position(Located(..))-import Cryptol.ModuleSystem.Name-import Cryptol.TypeCheck.AST-import Cryptol.TypeCheck.Subst(listParamSubst, apSubst)-import Cryptol.TypeCheck.SimpType(tRebuild)--{--XXX: Should we simplify constraints in the instantiated modules?--If so, we also need to adjust the constraint parameters on terms appropriately,-especially when working with dictionaries.--}----- | Convert a module instantiation into a partial module.--- The resulting module is incomplete because it is missing the definitions--- from the instantiation.-instantiateModule :: FreshM m =>- Module {- ^ Parametrized module -} ->- ModName {- ^ Name of the new module -} ->- Map TParam Type {- ^ Type params -} ->- Map Name Expr {- ^ Value parameters -} ->- m (Name -> Name, [Located Prop], Module)- -- ^ Renaming, instantiated constraints, fresh module, new supply-instantiateModule func newName tpMap vpMap- | not (null (mSubModules func)) =- panic "instantiateModule"- [ "XXX: we don't support functors with nested moduels yet." ]- | otherwise =- runReaderT (TopModule newName) $- do let oldVpNames = Map.keys vpMap- newVpNames <- mapM freshParamName (Map.keys vpMap)- let vpNames = Map.fromList (zip oldVpNames newVpNames)-- env <- computeEnv func tpMap vpNames- let ren x = case nameNamespace x of- NSValue -> Map.findWithDefault x x (funNameMap env)- NSType -> Map.findWithDefault x x (tyNameMap env)- NSModule -> x-- let rnMp :: Inst a => (a -> Name) -> Map Name a -> Map Name a- rnMp f m = Map.fromList [ (f x, x) | a <- Map.elems m- , let x = inst env a ]-- renamedExports = inst env (mExports func)- renamedTySyns = rnMp tsName (mTySyns func)- renamedNewtypes = rnMp ntName (mNewtypes func)- renamedPrimTys = rnMp atName (mPrimTypes func)-- su = listParamSubst (Map.toList (tyParamMap env))-- goals = map (fmap (apSubst su)) (mParamConstraints func)- -- Constraints to discharge about the type instances-- let renamedDecls = inst env (mDecls func)- paramDecls = map (mkParamDecl su vpNames) (Map.toList vpMap)-- return ( ren- , goals- , Module- { mName = newName- , mExports = renamedExports- , mImports = mImports func- , mTySyns = renamedTySyns- , mNewtypes = renamedNewtypes- , mPrimTypes = renamedPrimTys- , mParamTypes = Map.empty- , mParamConstraints = []- , mParamFuns = Map.empty- , mDecls = paramDecls ++ renamedDecls-- , mSubModules = mempty- , mFunctors = mempty- } )-- where- mkParamDecl su vpNames (x,e) =- NonRecursive Decl- { dName = Map.findWithDefault (error "OOPS") x vpNames- , dSignature = apSubst su- $ mvpType- $ Map.findWithDefault (error "UUPS") x (mParamFuns func)- , dDefinition = DExpr e- , dPragmas = [] -- XXX: which if any pragmas?- , dInfix = False -- XXX: get from parameter?- , dFixity = Nothing -- XXX: get from parameter- , dDoc = Nothing -- XXX: get from parametr(or instance?)- }-------------------------------------------------------------------------------------- Things that need to be renamed--class Defines t where- defines :: t -> Set Name--instance Defines t => Defines [t] where- defines = Set.unions . map defines--instance Defines Decl where- defines = Set.singleton . dName--instance Defines DeclGroup where- defines d =- case d of- NonRecursive x -> defines x- Recursive x -> defines x-------------------------------------------------------------------------------------type InstM = ReaderT ModPath---- | Generate a new instance of a declared name.-freshenName :: FreshM m => Name -> InstM m Name-freshenName x =- do m <- ask- let sys = case nameInfo x of- Declared _ s -> s- _ -> UserName- liftSupply (mkDeclared (nameNamespace x)- m sys (nameIdent x) (nameFixity x) (nameLoc x))--freshParamName :: FreshM m => Name -> InstM m Name-freshParamName x =- do m <- ask- let newName = modParamIdent (nameIdent x)- liftSupply (mkDeclared (nameNamespace x)- m UserName newName (nameFixity x) (nameLoc x))------- | Compute renaming environment from a module instantiation.--- computeEnv :: ModInst -> InstM Env-computeEnv :: FreshM m =>- Module {- ^ Functor being instantiated -} ->- Map TParam Type {- replace type params by type -} ->- Map Name Name {- replace value parameters by other names -} ->- InstM m Env-computeEnv m tpMap vpMap =- do tss <- mapM freshTy (Map.toList (mTySyns m))- nts <- mapM freshTy (Map.toList (mNewtypes m))- let tnMap = Map.fromList (tss ++ nts)-- defHere <- mapM mkVParam (Set.toList (defines (mDecls m)))- let fnMap = Map.union vpMap (Map.fromList defHere)-- return Env { funNameMap = fnMap- , tyNameMap = tnMap- , tyParamMap = tpMap- }- where- freshTy (x,_) = do y <- freshenName x- return (x,y)-- mkVParam x = do y <- freshenName x- return (x,y)--------------------------------------------------------------------------------------- Do the renaming--data Env = Env- { funNameMap :: Map Name Name- , tyNameMap :: Map Name Name- , tyParamMap :: Map TParam Type- } deriving Show---class Inst t where- inst :: Env -> t -> t--instance Inst a => Inst [a] where- inst env = map (inst env)--instance Inst Expr where- inst env = go- where- go expr =- case expr of- EVar x -> case Map.lookup x (funNameMap env) of- Just y -> EVar y- _ -> expr-- ELocated r e -> ELocated r (inst env e)- EList xs t -> EList (inst env xs) (inst env t)- ETuple es -> ETuple (inst env es)- ERec xs -> ERec (fmap go xs)- ESel e s -> ESel (go e) s- ESet ty e x v -> ESet (inst env ty) (go e) x (go v)- EIf e1 e2 e3 -> EIf (go e1) (go e2) (go e3)- EComp t1 t2 e mss -> EComp (inst env t1) (inst env t2)- (go e)- (inst env mss)- ETAbs t e -> ETAbs t (go e)- ETApp e t -> ETApp (go e) (inst env t)- EApp e1 e2 -> EApp (go e1) (go e2)- EAbs x t e -> EAbs x (inst env t) (go e)- EProofAbs p e -> EProofAbs (inst env p) (go e)- EProofApp e -> EProofApp (go e)- EWhere e ds -> EWhere (go e) (inst env ds)---instance Inst DeclGroup where- inst env dg =- case dg of- NonRecursive d -> NonRecursive (inst env d)- Recursive ds -> Recursive (inst env ds)--instance Inst DeclDef where- inst env d =- case d of- DPrim -> DPrim- DExpr e -> DExpr (inst env e)--instance Inst Decl where- inst env d = d { dSignature = inst env (dSignature d)- , dDefinition = inst env (dDefinition d)- , dName = Map.findWithDefault (dName d) (dName d)- (funNameMap env)- }--instance Inst Match where- inst env m =- case m of- From x t1 t2 e -> From x (inst env t1) (inst env t2) (inst env e)- Let d -> Let (inst env d)--instance Inst Schema where- inst env s = s { sProps = inst env (sProps s)- , sType = inst env (sType s)- }--instance Inst Type where- inst env ty =- tRebuild $- case ty of- TCon tc ts -> TCon (inst env tc) (inst env ts)- TVar tv ->- case tv of- TVBound tp | Just t <- Map.lookup tp (tyParamMap env) -> t- _ -> ty- TUser x ts t -> TUser y (inst env ts) (inst env t)- where y = Map.findWithDefault x x (tyNameMap env)- TRec fs -> TRec (fmap (inst env) fs)- TNewtype nt ts -> TNewtype (inst env nt) (inst env ts)--instance Inst TCon where- inst env tc =- case tc of- TC x -> TC (inst env x)- _ -> tc--instance Inst TC where- inst env tc =- case tc of- TCAbstract x -> TCAbstract (inst env x)- _ -> tc--instance Inst UserTC where- inst env (UserTC x t) = UserTC y t- where y = Map.findWithDefault x x (tyNameMap env)--instance Inst (ExportSpec Name) where- inst env (ExportSpec spec) = ExportSpec (Map.mapWithKey doNS spec)- where- doNS ns =- case ns of- NSType -> Set.map \x -> Map.findWithDefault x x (tyNameMap env)- NSValue -> Set.map \x -> Map.findWithDefault x x (funNameMap env)- NSModule -> id---instance Inst TySyn where- inst env ts = TySyn { tsName = instTyName env x- , tsParams = tsParams ts- , tsConstraints = inst env (tsConstraints ts)- , tsDef = inst env (tsDef ts)- , tsDoc = tsDoc ts- }- where x = tsName ts--instance Inst Newtype where- inst env nt = Newtype { ntName = instTyName env x- , ntParams = ntParams nt- , ntConstraints = inst env (ntConstraints nt)- , ntFields = fmap (inst env) (ntFields nt)- , ntDoc = ntDoc nt- }- where x = ntName nt--instance Inst AbstractType where- inst env a = AbstractType { atName = instTyName env (atName a)- , atKind = atKind a- , atCtrs = case atCtrs a of- (xs,ps) -> (xs, inst env ps)- , atFixitiy = atFixitiy a- , atDoc = atDoc a- }--instTyName :: Env -> Name -> Name-instTyName env x = Map.findWithDefault x x (tyNameMap env)------
src/Cryptol/ModuleSystem/Interface.hs view
@@ -9,30 +9,28 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE Safe #-} module Cryptol.ModuleSystem.Interface ( Iface , IfaceG(..) , IfaceDecls(..)- , IfaceTySyn, ifTySynName- , IfaceNewtype , IfaceDecl(..)- , IfaceParams(..)+ , IfaceNames(..)+ , ifModName , emptyIface , ifacePrimMap- , noIfaceParams- , isEmptyIfaceParams+ , ifaceForgetName , ifaceIsFunctor- , flatPublicIface- , flatPublicDecls , filterIfaceDecls , ifaceDeclsNames+ , ifaceOrigNameMap ) where import Data.Set(Set) import qualified Data.Set as Set+import Data.Map (Map) import qualified Data.Map as Map import Data.Semigroup import Data.Text (Text)@@ -44,74 +42,76 @@ import Prelude.Compat import Cryptol.ModuleSystem.Name-import Cryptol.Utils.Ident (ModName)+import Cryptol.Utils.Ident (ModName, OrigName(..)) import Cryptol.Utils.Panic(panic) import Cryptol.Utils.Fixity(Fixity) import Cryptol.Parser.AST(Pragma)-import Cryptol.Parser.Position(Located) import Cryptol.TypeCheck.Type +type Iface = IfaceG ModName --- | The resulting interface generated by a module that has been typechecked.-data IfaceG mname = Iface- { ifModName :: !mname -- ^ Module name- , ifPublic :: IfaceDecls -- ^ Exported definitions- , ifPrivate :: IfaceDecls -- ^ Private defintiions- , ifParams :: IfaceParams -- ^ Uninterpreted constants (aka module params)+-- | The interface repersenting a typecheck top-level module.+data IfaceG name = Iface+ { ifNames :: IfaceNames name -- ^ Info about names in this module+ , ifParams :: FunctorParams -- ^ Module parameters, if any+ , ifDefines :: IfaceDecls -- ^ All things defines in the module+ -- (includes nested definitions) } deriving (Show, Generic, NFData) -ifaceIsFunctor :: IfaceG mname -> Bool-ifaceIsFunctor = not . isEmptyIfaceParams . ifParams---- | The public declarations in all modules, including nested--- The modules field contains public functors--- Assumes that we are not a functor.-flatPublicIface :: IfaceG mname -> IfaceDecls-flatPublicIface iface = flatPublicDecls (ifPublic iface)---flatPublicDecls :: IfaceDecls -> IfaceDecls-flatPublicDecls ifs = mconcat ( ifs { ifModules = fun }- : map flatPublicIface (Map.elems nofun)- )+-- | Remove the name of a module. This is useful for dealing with collections+-- of modules, as in `Map (ImpName Name) (IfaceG ())`.+ifaceForgetName :: IfaceG name -> IfaceG ()+ifaceForgetName i = i { ifNames = newNames }+ where newNames = (ifNames i) { ifsName = () } - where- (fun,nofun) = Map.partition ifaceIsFunctor (ifModules ifs)+-- | Access the name of a module.+ifModName :: IfaceG name -> name+ifModName = ifsName . ifNames +-- | Information about the names in a module.+data IfaceNames name = IfaceNames+ { ifsName :: name -- ^ Name of this submodule+ , ifsNested :: Set Name -- ^ Things nested in this module+ , ifsDefines :: Set Name -- ^ Things defined in this module+ , ifsPublic :: Set Name -- ^ Subset of `ifsDefines` that is public+ , ifsDoc :: !(Maybe Text) -- ^ Documentation+ } deriving (Show, Generic, NFData) -type Iface = IfaceG ModName+-- | Is this interface for a functor.+ifaceIsFunctor :: IfaceG name -> Bool+ifaceIsFunctor = not . Map.null . ifParams -emptyIface :: mname -> IfaceG mname+emptyIface :: ModName -> Iface emptyIface nm = Iface- { ifModName = nm- , ifPublic = mempty- , ifPrivate = mempty- , ifParams = noIfaceParams- }--data IfaceParams = IfaceParams- { ifParamTypes :: Map.Map Name ModTParam- , ifParamConstraints :: [Located Prop] -- ^ Constraints on param. types- , ifParamFuns :: Map.Map Name ModVParam- } deriving (Show, Generic, NFData)--noIfaceParams :: IfaceParams-noIfaceParams = IfaceParams- { ifParamTypes = Map.empty- , ifParamConstraints = []- , ifParamFuns = Map.empty+ { ifNames = IfaceNames { ifsName = nm+ , ifsDefines = mempty+ , ifsPublic = mempty+ , ifsNested = mempty+ , ifsDoc = Nothing+ }+ , ifParams = mempty+ , ifDefines = mempty } -isEmptyIfaceParams :: IfaceParams -> Bool-isEmptyIfaceParams IfaceParams { .. } =- Map.null ifParamTypes && null ifParamConstraints && Map.null ifParamFuns-+-- | Declarations in a module. Note that this includes things from nested+-- modules, but not things from nested functors, which are in `ifFunctors`. data IfaceDecls = IfaceDecls- { ifTySyns :: Map.Map Name IfaceTySyn- , ifNewtypes :: Map.Map Name IfaceNewtype- , ifAbstractTypes :: Map.Map Name IfaceAbstractType+ { ifTySyns :: Map.Map Name TySyn+ , ifNewtypes :: Map.Map Name Newtype+ , ifAbstractTypes :: Map.Map Name AbstractType , ifDecls :: Map.Map Name IfaceDecl- , ifModules :: !(Map.Map Name (IfaceG Name))+ , ifModules :: !(Map.Map Name (IfaceNames Name))+ , ifSignatures :: !(Map.Map Name ModParamNames)+ , ifFunctors :: !(Map.Map Name (IfaceG Name))+ {- ^ XXX: Maybe arg info?+ Also, with the current implementation we aim to complete remove functors+ by essentially inlining them. To achieve this with just interfaces+ we'd have to store here the entire module, not just its interface.+ At the moment we work around this by passing all loaded modules to the+ type checker, so it looks up functors there, instead of in the interfaces,+ but we'd need to change this if we want better support for separate+ compilation. -}+ } deriving (Show, Generic, NFData) filterIfaceDecls :: (Name -> Bool) -> IfaceDecls -> IfaceDecls@@ -121,6 +121,8 @@ , ifAbstractTypes = filterMap (ifAbstractTypes ifs) , ifDecls = filterMap (ifDecls ifs) , ifModules = filterMap (ifModules ifs)+ , ifFunctors = filterMap (ifFunctors ifs)+ , ifSignatures = filterMap (ifSignatures ifs) } where filterMap :: Map.Map Name a -> Map.Map Name a@@ -132,6 +134,8 @@ , Map.keysSet (ifAbstractTypes i) , Map.keysSet (ifDecls i) , Map.keysSet (ifModules i)+ , Map.keysSet (ifFunctors i)+ , Map.keysSet (ifSignatures i) ] @@ -142,30 +146,35 @@ , ifAbstractTypes = Map.union (ifAbstractTypes l) (ifAbstractTypes r) , ifDecls = Map.union (ifDecls l) (ifDecls r) , ifModules = Map.union (ifModules l) (ifModules r)+ , ifFunctors = Map.union (ifFunctors l) (ifFunctors r)+ , ifSignatures = ifSignatures l <> ifSignatures r } instance Monoid IfaceDecls where- mempty = IfaceDecls Map.empty Map.empty Map.empty Map.empty Map.empty- mappend = (<>)+ mempty = IfaceDecls+ { ifTySyns = mempty+ , ifNewtypes = mempty+ , ifAbstractTypes = mempty+ , ifDecls = mempty+ , ifModules = mempty+ , ifFunctors = mempty+ , ifSignatures = mempty+ }+ mappend = (<>) mconcat ds = IfaceDecls { ifTySyns = Map.unions (map ifTySyns ds) , ifNewtypes = Map.unions (map ifNewtypes ds) , ifAbstractTypes = Map.unions (map ifAbstractTypes ds) , ifDecls = Map.unions (map ifDecls ds) , ifModules = Map.unions (map ifModules ds)+ , ifFunctors = Map.unions (map ifFunctors ds)+ , ifSignatures = Map.unions (map ifSignatures ds) } -type IfaceTySyn = TySyn--ifTySynName :: TySyn -> Name-ifTySynName = tsName--type IfaceNewtype = Newtype-type IfaceAbstractType = AbstractType- data IfaceDecl = IfaceDecl { ifDeclName :: !Name -- ^ Name of thing , ifDeclSig :: Schema -- ^ Type+ , ifDeclIsPrim :: !Bool , ifDeclPragmas :: [Pragma] -- ^ Pragmas , ifDeclInfix :: Bool -- ^ Is this an infix thing , ifDeclFixity :: Maybe Fixity -- ^ Fixity information@@ -176,15 +185,12 @@ -- | Produce a PrimMap from an interface. -- -- NOTE: the map will expose /both/ public and private names.+-- NOTE: this is a bit misnamed, as it is used to resolve known names+-- that Cryptol introduces (e.g., during type checking). These+-- names need not be primitives. A better way to do this in the future+-- might be to use original names instead (see #1522). ifacePrimMap :: Iface -> PrimMap-ifacePrimMap Iface { .. } =- PrimMap { primDecls = merge primDecls- , primTypes = merge primTypes }- where- merge f = Map.union (f public) (f private)-- public = ifaceDeclsPrimMap ifPublic- private = ifaceDeclsPrimMap ifPrivate+ifacePrimMap = ifaceDeclsPrimMap . ifDefines ifaceDeclsPrimMap :: IfaceDecls -> PrimMap ifaceDeclsPrimMap IfaceDecls { .. } =@@ -199,6 +205,36 @@ [ "Top level name not declared in a module?" , show n ] - exprs = map entry (Map.keys ifDecls) newtypes = map entry (Map.keys ifNewtypes)+ exprs = map entry (Map.keys ifDecls) types = map entry (Map.keys ifTySyns)+++-- | Given an interface computing a map from original names to actual names,+-- grouped by namespace.+ifaceOrigNameMap :: IfaceG name -> Map Namespace (Map OrigName Name)+ifaceOrigNameMap ifa = Map.unionsWith Map.union (here : nested)+ where+ here = Map.fromList $+ [ (NSValue, toMap vaNames) | not (Set.null vaNames) ] +++ [ (NSType, toMap tyNames) | not (Set.null tyNames) ] +++ [ (NSValue, toMap moNames) | not (Set.null moNames) ]++ nested = map ifaceOrigNameMap (Map.elems (ifFunctors decls))++ toMap names = Map.fromList+ [ (og,x) | x <- Set.toList names, Just og <- [ asOrigName x ] ]++ decls = ifDefines ifa+ from f = Map.keysSet (f decls)+ tyNames = Set.unions [ from ifTySyns, from ifNewtypes, from ifAbstractTypes ]+ moNames = Set.unions [ from ifModules, from ifSignatures, from ifFunctors ]+ vaNames = Set.unions [ newtypeCons, from ifDecls ]+ newtypeCons = Set.fromList (map ntConName (Map.elems (ifNewtypes decls)))+++++++
src/Cryptol/ModuleSystem/Monad.hs view
@@ -10,29 +10,33 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE BlockArguments #-} module Cryptol.ModuleSystem.Monad where import Cryptol.Eval (EvalEnv,EvalOpts(..)) +import Cryptol.Backend.FFI (ForeignSrc)+import Cryptol.Backend.FFI.Error import qualified Cryptol.Backend.Monad as E import Cryptol.ModuleSystem.Env-import Cryptol.ModuleSystem.Fingerprint+import qualified Cryptol.ModuleSystem.Env as MEnv import Cryptol.ModuleSystem.Interface import Cryptol.ModuleSystem.Name (FreshM(..),Supply) import Cryptol.ModuleSystem.Renamer (RenamerError(),RenamerWarning()) import Cryptol.ModuleSystem.NamingEnv(NamingEnv) import qualified Cryptol.Parser as Parser import qualified Cryptol.Parser.AST as P-import Cryptol.Parser.Position (Located) import Cryptol.Utils.Panic (panic) import qualified Cryptol.Parser.NoPat as NoPat+import qualified Cryptol.Parser.ExpandPropGuards as ExpandPropGuards import qualified Cryptol.Parser.NoInclude as NoInc import qualified Cryptol.TypeCheck as T import qualified Cryptol.TypeCheck.AST as T import qualified Cryptol.TypeCheck.Solver.SMT as SMT -import Cryptol.Parser.Position (Range)+import Cryptol.Parser.Position (Range, Located) import Cryptol.Utils.Ident (interactiveName, noModuleName) import Cryptol.Utils.PP import Cryptol.Utils.Logger(Logger)@@ -42,9 +46,10 @@ import Control.Exception (IOException) import Data.ByteString (ByteString) import Data.Function (on)+import Data.Functor.Identity import Data.Map (Map)-import Data.Maybe (isJust) import Data.Text.Encoding.Error (UnicodeException)+import Data.Traversable import MonadLib import System.Directory (canonicalizePath) @@ -60,6 +65,7 @@ data ImportSource = FromModule P.ModName | FromImport (Located P.Import)+ | FromSigImport (Located P.ModName) | FromModuleInstance (Located P.ModName) deriving (Show, Generic, NFData) @@ -70,6 +76,7 @@ ppPrec _ is = case is of FromModule n -> text "module name" <+> pp n FromImport li -> text "import of module" <+> pp (P.iModule (P.thing li))+ FromSigImport l -> text "import of interface" <+> pp (P.thing l) FromModuleInstance l -> text "instantiation of module" <+> pp (P.thing l) @@ -79,6 +86,7 @@ FromModule n -> n FromImport li -> P.iModule (P.thing li) FromModuleInstance l -> P.thing l+ FromSigImport l -> P.thing l data ModuleError@@ -98,6 +106,8 @@ -- ^ Problems during the renaming phase | NoPatErrors ImportSource [NoPat.Error] -- ^ Problems during the NoPat phase+ | ExpandPropGuardsError ImportSource ExpandPropGuards.Error+ -- ^ Problems during the ExpandPropGuards phase | NoIncludeErrors ImportSource [NoInc.IncludeError] -- ^ Problems during the NoInclude phase | TypeCheckingFailed ImportSource T.NameMap [(Range,T.Error)]@@ -108,11 +118,8 @@ -- ^ Module loaded by 'import' statement has the wrong module name | DuplicateModuleName P.ModName FilePath FilePath -- ^ Two modules loaded from different files have the same module name- | ImportedParamModule P.ModName- -- ^ Attempt to import a parametrized module that was not instantiated.- | FailedToParameterizeModDefs P.ModName [T.Name]- -- ^ Failed to add the module parameters to all definitions in a module.- | NotAParameterizedModule P.ModName+ | FFILoadErrors P.ModName [FFILoadError]+ -- ^ Errors loading foreign function implementations | ErrorInFile ModulePath ModuleError -- ^ This is just a tag on the error, indicating the file containing it.@@ -131,6 +138,7 @@ RecursiveModules mods -> mods `deepseq` () RenamerErrors src errs -> src `deepseq` errs `deepseq` () NoPatErrors src errs -> src `deepseq` errs `deepseq` ()+ ExpandPropGuardsError src err -> src `deepseq` err `deepseq` () NoIncludeErrors src errs -> src `deepseq` errs `deepseq` () TypeCheckingFailed nm src errs -> nm `deepseq` src `deepseq` errs `deepseq` () ModuleNameMismatch expected found ->@@ -138,9 +146,7 @@ DuplicateModuleName name path1 path2 -> name `deepseq` path1 `deepseq` path2 `deepseq` () OtherFailure x -> x `deepseq` ()- ImportedParamModule x -> x `deepseq` ()- FailedToParameterizeModDefs x xs -> x `deepseq` xs `deepseq` ()- NotAParameterizedModule x -> x `deepseq` ()+ FFILoadErrors x errs -> x `deepseq` errs `deepseq` () ErrorInFile x y -> x `deepseq` y `deepseq` () instance PP ModuleError where@@ -178,6 +184,8 @@ NoPatErrors _src errs -> vcat (map pp errs) + ExpandPropGuardsError _src err -> pp err+ NoIncludeErrors _src errs -> vcat (map NoInc.ppIncludeError errs) TypeCheckingFailed _src nm errs -> vcat (map (T.ppNamedError nm) errs)@@ -185,7 +193,7 @@ ModuleNameMismatch expected found -> hang (text "[error]" <+> pp (P.srcRange found) <.> char ':') 4 (vcat [ text "File name does not match module name:"- , text "Saw:" <+> pp (P.thing found)+ , text " Actual:" <+> pp (P.thing found) , text "Expected:" <+> pp expected ]) @@ -196,16 +204,10 @@ OtherFailure x -> text x - ImportedParamModule p ->- text "[error] Import of a non-instantiated parameterized module:" <+> pp p-- FailedToParameterizeModDefs x xs ->- hang (text "[error] Parameterized module" <+> pp x <+>- text "has polymorphic parameters:")- 4 (commaSep (map pp xs))-- NotAParameterizedModule x ->- text "[error] Module" <+> pp x <+> text "does not have parameters."+ FFILoadErrors x errs ->+ hang (text "[error] Failed to load foreign implementations for module"+ <+> pp x <.> colon)+ 4 (vcat $ map pp errs) ErrorInFile _ x -> ppPrec prec x @@ -238,6 +240,11 @@ src <- getImportSource ModuleT (raise (NoPatErrors src errs)) +expandPropGuardsError :: ExpandPropGuards.Error -> ModuleM a+expandPropGuardsError err = do+ src <- getImportSource+ ModuleT (raise (ExpandPropGuardsError src err))+ noIncludeErrors :: [NoInc.IncludeError] -> ModuleM a noIncludeErrors errs = do src <- getImportSource@@ -256,15 +263,8 @@ duplicateModuleName name path1 path2 = ModuleT (raise (DuplicateModuleName name path1 path2)) -importParamModule :: P.ModName -> ModuleM a-importParamModule x = ModuleT (raise (ImportedParamModule x))--failedToParameterizeModDefs :: P.ModName -> [T.Name] -> ModuleM a-failedToParameterizeModDefs x xs =- ModuleT (raise (FailedToParameterizeModDefs x xs))--notAParameterizedModule :: P.ModName -> ModuleM a-notAParameterizedModule x = ModuleT (raise (NotAParameterizedModule x))+ffiLoadErrors :: P.ModName -> [FFILoadError] -> ModuleM a+ffiLoadErrors x errs = ModuleT (raise (FFILoadErrors x errs)) -- | Run the computation, and if it caused and error, tag the error -- with the given file.@@ -423,13 +423,17 @@ env <- get set $! f env -getLoadedMaybe :: P.ModName -> ModuleM (Maybe LoadedModule)+getLoadedMaybe :: P.ModName -> ModuleM (Maybe (LoadedModuleG T.TCTopEntity)) getLoadedMaybe mn = ModuleT $ do env <- get- return (lookupModule mn env)+ return (lookupTCEntity mn env) +-- | This checks if the given name is loaded---it might refer to either+-- a module or a signature. isLoaded :: P.ModName -> ModuleM Bool-isLoaded mn = isJust <$> getLoadedMaybe mn+isLoaded mn =+ do env <- ModuleT get+ pure (MEnv.isLoaded mn (meLoadedModules env)) loadingImport :: Located P.Import -> ModuleM a -> ModuleM a loadingImport = loading . FromImport@@ -448,12 +452,12 @@ loading :: ImportSource -> ModuleM a -> ModuleM a loading src m = ModuleT $ do ro <- ask- let ro' = ro { roLoading = src : roLoading ro }+ let new = src : roLoading ro -- check for recursive modules- when (src `elem` roLoading ro) (raise (RecursiveModules (roLoading ro')))+ when (src `elem` roLoading ro) (raise (RecursiveModules new)) - local ro' (unModuleT m)+ local ro { roLoading = new } (unModuleT m) -- | Get the currently focused import source. getImportSource :: ModuleM ImportSource@@ -463,17 +467,17 @@ is : _ -> return is _ -> return (FromModule noModuleName) -getIface :: P.ModName -> ModuleM Iface-getIface mn = ($ mn) <$> getIfaces--getIfaces :: ModuleM (P.ModName -> Iface)-getIfaces = doLookup <$> ModuleT get+getIfaces :: ModuleM (Map P.ModName (Either T.ModParamNames Iface))+getIfaces = toMap <$> ModuleT get where- doLookup env mn =- case lookupModule mn env of- Just lm -> lmInterface lm- Nothing -> panic "ModuleSystem" ["Interface not available", show (pp mn)]+ toMap env = cvt <$> getLoadedEntities (meLoadedModules env) + cvt ent =+ case ent of+ ALoadedInterface ifa -> Left (lmData ifa)+ ALoadedFunctor mo -> Right (lmdInterface (lmData mo))+ ALoadedModule mo -> Right (lmdInterface (lmData mo))+ getLoaded :: P.ModName -> ModuleM T.Module getLoaded mn = ModuleT $ do env <- get@@ -481,6 +485,20 @@ Just lm -> return (lmModule lm) Nothing -> panic "ModuleSystem" ["Module not available", show (pp mn) ] +getAllLoaded :: ModuleM (P.ModName -> Maybe (T.ModuleG (), IfaceG ()))+getAllLoaded = ModuleT+ do env <- get+ pure \nm -> do lm <- lookupModule nm env+ pure ( (lmModule lm) { T.mName = () }+ , ifaceForgetName (lmInterface lm)+ )++getAllLoadedSignatures :: ModuleM (P.ModName -> Maybe T.ModParamNames)+getAllLoadedSignatures = ModuleT+ do env <- get+ pure \nm -> lmData <$> lookupSignature nm env++ getNameSeeds :: ModuleM T.NameSeeds getNameSeeds = ModuleT (meNameSeeds `fmap` get) @@ -505,28 +523,42 @@ do env <- get set $! env { meSupply = supply } -unloadModule :: (LoadedModule -> Bool) -> ModuleM ()+unloadModule :: (forall a. LoadedModuleG a -> Bool) -> ModuleM () unloadModule rm = ModuleT $ do env <- get set $! env { meLoadedModules = removeLoadedModule rm (meLoadedModules env) } loadedModule ::- ModulePath -> Fingerprint -> NamingEnv -> T.Module -> ModuleM ()-loadedModule path fp nameEnv m = ModuleT $ do+ ModulePath ->+ FileInfo ->+ NamingEnv ->+ Maybe ForeignSrc ->+ T.TCTopEntity ->+ ModuleM ()+loadedModule path fi nameEnv fsrc m = ModuleT $ do env <- get ident <- case path of InFile p -> unModuleT $ io (canonicalizePath p) InMem l _ -> pure l - set $! env { meLoadedModules = addLoadedModule path ident fp nameEnv m- (meLoadedModules env) }+ let newLM =+ case m of+ T.TCTopModule mo -> addLoadedModule path ident fi nameEnv fsrc mo+ T.TCTopSignature x s -> addLoadedSignature path ident fi nameEnv x s -modifyEvalEnv :: (EvalEnv -> E.Eval EvalEnv) -> ModuleM ()-modifyEvalEnv f = ModuleT $ do+ set $! env { meLoadedModules = newLM (meLoadedModules env) }+++modifyEvalEnvM :: Traversable t =>+ (EvalEnv -> E.Eval (t EvalEnv)) -> ModuleM (t ())+modifyEvalEnvM f = ModuleT $ do env <- get let evalEnv = meEvalEnv env- evalEnv' <- inBase $ E.runEval mempty (f evalEnv)- set $! env { meEvalEnv = evalEnv' }+ tenv <- inBase (E.runEval mempty (f evalEnv))+ traverse (\evalEnv' -> set $! env { meEvalEnv = evalEnv' }) tenv++modifyEvalEnv :: (EvalEnv -> E.Eval EvalEnv) -> ModuleM ()+modifyEvalEnv = fmap runIdentity . modifyEvalEnvM . (fmap Identity .) getEvalEnv :: ModuleM EvalEnv getEvalEnv = ModuleT (meEvalEnv `fmap` get)
src/Cryptol/ModuleSystem/Name.hs view
@@ -6,16 +6,15 @@ -- Stability : provisional -- Portability : portable -{-# LANGUAGE Trustworthy #-}- {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE RankNTypes #-} -- for the instances of RunM and BaseM {-# LANGUAGE UndecidableInstances #-} @@ -25,12 +24,17 @@ , NameSource(..) , nameUnique , nameIdent+ , mapNameIdent , nameInfo , nameLoc , nameFixity , nameNamespace , asPrim , asOrigName+ , nameModPath+ , nameModPathMaybe+ , nameTopModule+ , nameTopModuleMaybe , ppLocName , Namespace(..) , ModPath(..)@@ -38,15 +42,15 @@ -- ** Creation , mkDeclared- , mkParameter- , toParamInstName- , asParamName- , paramModRecParam+ , mkLocal+ , asLocal+ , mkModParam -- ** Unique Supply , FreshM(..), nextUniqueM- , SupplyT(), runSupplyT+ , SupplyT(), runSupplyT, runSupply , Supply(), emptySupply, nextUnique+ , freshNameFor -- ** PrimMap , PrimMap(..)@@ -57,6 +61,7 @@ import Control.DeepSeq import qualified Data.Map as Map import qualified Data.Monoid as M+import Data.Functor.Identity(runIdentity) import GHC.Generics (Generic) import MonadLib import Prelude ()@@ -66,36 +71,24 @@ -import Cryptol.Parser.Position (Range,Located(..),emptyRange)+import Cryptol.Parser.Position (Range,Located(..)) import Cryptol.Utils.Fixity import Cryptol.Utils.Ident import Cryptol.Utils.Panic import Cryptol.Utils.PP -+data NameInfo = GlobalName NameSource OrigName+ | LocalName Namespace Ident+ deriving (Generic, NFData, Show) -- Names -------------------------------------------------------------------------- | Information about the binding site of the name.-data NameInfo = Declared !ModPath !NameSource- -- ^ This name refers to a declaration from this module- | Parameter- -- ^ This name is a parameter (function or type)- deriving (Eq, Show, Generic, NFData)-- data Name = Name { nUnique :: {-# UNPACK #-} !Int -- ^ INVARIANT: this field uniquely identifies a name for one -- session with the Cryptol library. Names are unique to -- their binding site. , nInfo :: !NameInfo- -- ^ Information about the origin of this name. - , nNamespace :: !Namespace-- , nIdent :: !Ident- -- ^ The name of the identifier- , nFixity :: !(Maybe Fixity) -- ^ The associativity and precedence level of -- infix operators. 'Nothing' indicates an@@ -150,7 +143,12 @@ fmtPref og = case getNameFormat og disp of UnQualified -> "" Qualified q -> modNameToText q- NotInScope -> Text.pack $ show $ pp (ogModule og)+ NotInScope ->+ let m = Text.pack (show (pp (ogModule og)))+ in+ case ogSource og of+ FromModParam q -> m <> "::" <> Text.pack (show (pp q))+ _ -> m -- Note that this assumes that `xs` is `l` and `ys` is `r` cmpText xs ys =@@ -173,10 +171,13 @@ -- the need for parentheses. ppName :: Name -> Doc ppName nm =- case asOrigName nm of- Just og -> pp og- Nothing -> pp (nameIdent nm)-+ case nInfo nm of+ GlobalName _ og -> pp og+ LocalName _ i -> pp i+ <.>+ withPPCfg \cfg ->+ if ppcfgShowNameUniques cfg then "_" <.> int (nameUnique nm)+ else mempty instance PP Name where ppPrec _ = ppPrefixName@@ -184,12 +185,12 @@ instance PPName Name where ppNameFixity n = nameFixity n - ppInfixName n@Name { .. }- | isInfixIdent nIdent = ppName n+ ppInfixName n+ | isInfixIdent (nameIdent n) = ppName n | otherwise = panic "Name" [ "Non-infix name used infix"- , show nIdent ]+ , show (nameIdent n) ] - ppPrefixName n@Name { .. } = optParens (isInfixIdent nIdent) (ppName n)+ ppPrefixName n = optParens (isInfixIdent (nameIdent n)) (ppName n) -- | Pretty-print a name with its source location information.@@ -199,14 +200,26 @@ nameUnique :: Name -> Int nameUnique = nUnique +nameInfo :: Name -> NameInfo+nameInfo = nInfo+ nameIdent :: Name -> Ident-nameIdent = nIdent+nameIdent n = case nInfo n of+ GlobalName _ og -> ogName og+ LocalName _ i -> i -nameNamespace :: Name -> Namespace-nameNamespace = nNamespace+mapNameIdent :: (Ident -> Ident) -> Name -> Name+mapNameIdent f n =+ n { nInfo =+ case nInfo n of+ GlobalName x og -> GlobalName x og { ogName = f (ogName og) }+ LocalName x i -> LocalName x (f i)+ } -nameInfo :: Name -> NameInfo-nameInfo = nInfo+nameNamespace :: Name -> Namespace+nameNamespace n = case nInfo n of+ GlobalName _ og -> ogNamespace og+ LocalName ns _ -> ns nameLoc :: Name -> Range nameLoc = nLoc@@ -216,31 +229,43 @@ -- | Primtiives must be in a top level module, at least for now. asPrim :: Name -> Maybe PrimIdent-asPrim Name { .. } =- case nInfo of- Declared (TopModule m) _ -> Just $ PrimIdent m $ identText nIdent- _ -> Nothing--toParamInstName :: Name -> Name-toParamInstName n =+asPrim n = case nInfo n of- Declared m s -> n { nInfo = Declared (apPathRoot paramInstModName m) s }- Parameter -> n+ GlobalName _ og+ | TopModule m <- ogModule og, not (ogFromModParam og) ->+ Just $ PrimIdent m $ identText $ ogName og -asParamName :: Name -> Name-asParamName n = n { nInfo = Parameter }+ _ -> Nothing asOrigName :: Name -> Maybe OrigName-asOrigName nm =- case nInfo nm of- Declared p _ ->- Just OrigName { ogModule = apPathRoot notParamInstModName p- , ogNamespace = nNamespace nm- , ogName = nIdent nm- }- Parameter -> Nothing+asOrigName n =+ case nInfo n of+ GlobalName _ og -> Just og+ LocalName {} -> Nothing +-- | Get the module path for the given name.+nameModPathMaybe :: Name -> Maybe ModPath+nameModPathMaybe n = ogModule <$> asOrigName n +-- | Get the module path for the given name.+-- The name should be a top-level name.+nameModPath :: Name -> ModPath+nameModPath n =+ case nameModPathMaybe n of+ Just p -> p+ Nothing -> panic "nameModPath" [ "Not a top-level name: ", show n ]+++-- | Get the name of the top-level module that introduced this name.+nameTopModuleMaybe :: Name -> Maybe ModName+nameTopModuleMaybe = fmap topModuleFor . nameModPathMaybe++-- | Get the name of the top-level module that introduced this name.+-- Works only for top-level names (i.e., that have original names)+nameTopModule :: Name -> ModName+nameTopModule = topModuleFor . nameModPath++ -- Name Supply ----------------------------------------------------------------- class Monad m => FreshM m where@@ -271,6 +296,9 @@ runSupplyT :: Monad m => Supply -> SupplyT m a -> m (a,Supply) runSupplyT s (SupplyT m) = runStateT s m +runSupply :: Supply -> (forall m. FreshM m => m a) -> (a,Supply)+runSupply s m = runIdentity (runSupplyT s m)+ instance Monad m => Functor (SupplyT m) where fmap f (SupplyT m) = SupplyT (fmap f m) {-# INLINE fmap #-}@@ -315,8 +343,8 @@ emptySupply :: Supply emptySupply = Supply 0x1000 -- For one such name, see paramModRecParam--- XXX: perhaps we should simply not have such things, but that's the way--- for now.+-- XXX: perhaps we should simply not have such things+-- XXX: do we have these anymore? nextUnique :: Supply -> (Int,Supply) nextUnique (Supply n) = s' `seq` (n,s')@@ -330,26 +358,77 @@ mkDeclared :: Namespace -> ModPath -> NameSource -> Ident -> Maybe Fixity -> Range -> Supply -> (Name,Supply)-mkDeclared nNamespace m sys nIdent nFixity nLoc s =- let (nUnique,s') = nextUnique s- nInfo = Declared m sys- in (Name { .. }, s')+mkDeclared ns m sys ident fixity loc s = (name, s')+ where+ (u,s') = nextUnique s+ name = Name { nUnique = u+ , nFixity = fixity+ , nLoc = loc+ , nInfo = GlobalName+ sys+ OrigName+ { ogNamespace = ns+ , ogModule = m+ , ogName = ident+ , ogSource = FromDefinition+ }+ } -- | Make a new parameter name.-mkParameter :: Namespace -> Ident -> Range -> Supply -> (Name,Supply)-mkParameter nNamespace nIdent nLoc s =- let (nUnique,s') = nextUnique s- nFixity = Nothing- in (Name { nInfo = Parameter, .. }, s')+mkLocal :: Namespace -> Ident -> Range -> Supply -> (Name,Supply)+mkLocal ns ident loc s = (name, s')+ where+ (u,s') = nextUnique s+ name = Name { nUnique = u+ , nLoc = loc+ , nFixity = Nothing+ , nInfo = LocalName ns ident+ } -paramModRecParam :: Name-paramModRecParam = Name { nInfo = Parameter- , nFixity = Nothing- , nIdent = packIdent "$modParams"- , nLoc = emptyRange- , nUnique = 0x01- , nNamespace = NSValue- }+{- | Make a local name derived from the given name.+This is a bit questionable,+but it is used by the translation to SAW Core -}+asLocal :: Namespace -> Name -> Name+asLocal ns x =+ case nameInfo x of+ GlobalName _ og -> x { nInfo = LocalName ns (ogName og) }+ LocalName {} -> x++mkModParam ::+ ModPath {- ^ Module containing the parameter -} ->+ Ident {- ^ Name of the module parameter -} ->+ Range {- ^ Location -} ->+ Name {- ^ Name in the signature -} ->+ Supply -> (Name, Supply)+mkModParam own pname rng n s = (name, s')+ where+ (u,s') = nextUnique s+ name = Name { nUnique = u+ , nInfo = GlobalName+ UserName+ OrigName+ { ogModule = own+ , ogName = nameIdent n+ , ogNamespace = nameNamespace n+ , ogSource = FromModParam pname+ }+ , nFixity = nFixity n+ , nLoc = rng+ }++-- | This is used when instantiating functors+freshNameFor :: ModPath -> Name -> Supply -> (Name,Supply)+freshNameFor mpath x s = (newName, s1)+ where+ (u,s1) = nextUnique s+ newName =+ x { nUnique = u+ , nInfo =+ case nInfo x of+ GlobalName src og -> GlobalName src og { ogModule = mpath+ , ogSource = FromFunctorInst }+ LocalName {} -> panic "freshNameFor" ["Unexpected local",show x]+ } -- Prim Maps -------------------------------------------------------------------
+ src/Cryptol/ModuleSystem/Names.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE BlockArguments #-}+module Cryptol.ModuleSystem.Names where++import Data.Set(Set)+import qualified Data.Set as Set+import Control.DeepSeq(NFData)+import GHC.Generics (Generic)++import Cryptol.Utils.Panic (panic)+import Cryptol.ModuleSystem.Name+++-- | A non-empty collection of names used by the renamer.+data Names = One Name | Ambig (Set Name) -- ^ Non-empty+ deriving (Show,Generic,NFData)++namesToList :: Names -> [Name]+namesToList xs =+ case xs of+ One x -> [x]+ Ambig ns -> Set.toList ns++anyOne :: Names -> Name+anyOne = head . namesToList++instance Semigroup Names where+ xs <> ys =+ case (xs,ys) of+ (One x, One y)+ | x == y -> One x+ | otherwise -> Ambig $! Set.fromList [x,y]+ (One x, Ambig as) -> Ambig $! Set.insert x as+ (Ambig as, One x) -> Ambig $! Set.insert x as+ (Ambig as, Ambig bs) -> Ambig $! Set.union as bs++namesFromSet :: Set Name {- ^ Non-empty -} -> Names+namesFromSet xs =+ case Set.minView xs of+ Just (a,ys) -> if Set.null ys then One a else Ambig xs+ Nothing -> panic "namesFromSet" ["empty set"]++unionManyNames :: [Names] -> Maybe Names+unionManyNames xs =+ case xs of+ [] -> Nothing+ _ -> Just (foldr1 (<>) xs)++mapNames :: (Name -> Name) -> Names -> Names+mapNames f xs =+ case xs of+ One x -> One (f x)+ Ambig as -> namesFromSet (Set.map f as)++filterNames :: (Name -> Bool) -> Names -> Maybe Names+filterNames p names =+ case names of+ One x -> if p x then Just (One x) else Nothing+ Ambig xs -> do let ys = Set.filter p xs+ (y,zs) <- Set.minView ys+ if Set.null zs then Just (One y) else Just (Ambig ys)++travNames :: Applicative f => (Name -> f Name) -> Names -> f Names+travNames f xs =+ case xs of+ One x -> One <$> f x+ Ambig as -> namesFromSet . Set.fromList <$> traverse f (Set.toList as)+++-- Names that are in the first but not the second+diffNames :: Names -> Names -> Maybe Names+diffNames x y =+ case x of+ One a ->+ case y of+ One b -> if a == b then Nothing+ else Just (One a)+ Ambig xs -> if a `Set.member` xs then Nothing else Just (One a)+ Ambig xs ->+ do (a,rest) <- Set.minView ys+ pure if Set.null rest then One a else Ambig xs++ where+ ys = case y of+ One z -> Set.delete z xs+ Ambig zs -> Set.difference xs zs+
src/Cryptol/ModuleSystem/NamingEnv.hs view
@@ -7,112 +7,119 @@ -- Portability : portable {-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RecordWildCards #-} {-# 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 -import Data.List (nub)-import Data.Maybe (fromMaybe,mapMaybe,maybeToList)+import Data.Maybe (mapMaybe,maybeToList) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import Data.Set (Set) import qualified Data.Set as Set-import Data.Semigroup-import MonadLib (runId,Id,StateT,runStateT,lift,sets_,forM_)+import Data.Foldable(foldl') import GHC.Generics (Generic)-import Control.DeepSeq--import Prelude ()-import Prelude.Compat+import Control.DeepSeq(NFData) import Cryptol.Utils.PP import Cryptol.Utils.Panic (panic)+import Cryptol.Utils.Ident(allNamespaces) import Cryptol.Parser.AST-import Cryptol.Parser.Name(isGeneratedName)-import Cryptol.Parser.Position import qualified Cryptol.TypeCheck.AST as T-import Cryptol.ModuleSystem.Interface import Cryptol.ModuleSystem.Name+import Cryptol.ModuleSystem.Names+import Cryptol.ModuleSystem.Interface --- Naming Environment ----------------------------------------------------------- -- | The 'NamingEnv' is used by the renamer to determine what -- identifiers refer to.-newtype NamingEnv = NamingEnv (Map Namespace (Map PName [Name]))+newtype NamingEnv = NamingEnv (Map Namespace (Map PName Names)) deriving (Show,Generic,NFData) --- | All names mentioned in the environment-namingEnvNames :: NamingEnv -> Set Name-namingEnvNames (NamingEnv xs) =- Set.fromList $ concatMap (concat . Map.elems) $ Map.elems xs+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) --- | Get the names in a given namespace-namespaceMap :: Namespace -> NamingEnv -> Map PName [Name]-namespaceMap ns (NamingEnv env) = Map.findWithDefault Map.empty ns env+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)) --- | Resolve a name in the given namespace.-lookupNS :: Namespace -> PName -> NamingEnv -> [Name]-lookupNS ns x = Map.findWithDefault [] x . namespaceMap ns --- | Return a list of value-level names to which this parsed name may refer.-lookupValNames :: PName -> NamingEnv -> [Name]-lookupValNames = lookupNS NSValue---- | Return a list of type-level names to which this parsed name may refer.-lookupTypeNames :: PName -> NamingEnv -> [Name]-lookupTypeNames = lookupNS NSType+{- | This "joins" two naming environments by matching the text name.+The result maps the unique names from the first environment with the+matching names in the second. This is used to compute the naming for+an instantiated functor:+ * if the left environment has the defined names of the functor, and+ * the right one has the defined names of the instantiation, then+ * the result maps functor names to instance names.+-}+zipByTextName :: NamingEnv -> NamingEnv -> Map Name Name+zipByTextName (NamingEnv k) (NamingEnv v) = Map.fromList $ doInter doNS k v+ where+ doInter :: Ord k => (a -> b -> [c]) -> Map k a -> Map k b -> [c]+ doInter f a b = concat (Map.elems (Map.intersectionWith f a b)) --- | Singleton renaming environment for the given namespace.-singletonNS :: Namespace -> PName -> Name -> NamingEnv-singletonNS ns pn n = NamingEnv (Map.singleton ns (Map.singleton pn [n]))+ doNS :: Map PName Names -> Map PName Names -> [(Name,Name)]+ doNS as bs = doInter doPName as bs --- | Singleton expression renaming environment.-singletonE :: PName -> Name -> NamingEnv-singletonE = singletonNS NSValue+ doPName :: Names -> Names -> [(Name,Name)]+ doPName xs ys = [ (x,y) | x <- namesToList xs, y <- namesToList ys ]+ -- NOTE: we'd exepct that there are no ambiguities in the environments. --- | Singleton type renaming environment.-singletonT :: PName -> Name -> NamingEnv-singletonT = singletonNS NSType+-- | Keep only the bindings in the 1st environment that are *NOT* in the second.+without :: NamingEnv -> NamingEnv -> NamingEnv+NamingEnv keep `without` NamingEnv remove = NamingEnv result+ where+ result = Map.differenceWith rmInNS keep remove+ rmInNS a b = let c = Map.differenceWith diffNames a b+ in if Map.null c then Nothing else Just c +-- | All names mentioned in the environment+namingEnvNames :: NamingEnv -> Set Name+namingEnvNames (NamingEnv xs) =+ case unionManyNames (mapMaybe (unionManyNames . Map.elems) (Map.elems xs)) of+ Nothing -> Set.empty+ Just (One x) -> Set.singleton x+ Just (Ambig as) -> as -namingEnvRename :: (Name -> Name) -> NamingEnv -> NamingEnv-namingEnvRename f (NamingEnv mp) = NamingEnv (ren <$> mp)+-- | Get a unqualified naming environment for the given names+namingEnvFromNames :: Set Name -> NamingEnv+namingEnvFromNames xs = NamingEnv (foldl' add mempty xs) where- ren nsm = map f <$> nsm+ add mp x = let ns = nameNamespace x+ txt = nameIdent x+ in Map.insertWith (Map.unionWith (<>))+ ns (Map.singleton (mkUnqual txt) (One x))+ mp -instance Semigroup NamingEnv where- NamingEnv l <> NamingEnv r =- NamingEnv (Map.unionWith (Map.unionWith merge) l r)--instance Monoid NamingEnv where- mempty = NamingEnv Map.empty- {-# INLINE mempty #-}+-- | Get the names in a given namespace+namespaceMap :: Namespace -> NamingEnv -> Map PName Names+namespaceMap ns (NamingEnv env) = Map.findWithDefault Map.empty ns env +-- | Resolve a name in the given namespace.+lookupNS :: Namespace -> PName -> NamingEnv -> Maybe Names+lookupNS ns x env = Map.lookup x (namespaceMap ns env) --- | Merge two name maps, collapsing cases where the entries are the same, and--- producing conflicts otherwise.-merge :: [Name] -> [Name] -> [Name]-merge xs ys | xs == ys = xs- | otherwise = nub (xs ++ ys)+-- | Resolve a name in the given namespace.+lookupListNS :: Namespace -> PName -> NamingEnv -> [Name]+lookupListNS ns x env =+ case lookupNS ns x env of+ Nothing -> []+ Just as -> namesToList as -instance PP NamingEnv where- ppPrec _ (NamingEnv mps) = vcat $ map ppNS $ Map.toList mps- where ppNS (ns,xs) = pp ns $$ nest 2 (vcat (map ppNm (Map.toList xs)))- ppNm (x,as) = pp x <+> "->" <+> commaSep (map pp as)+-- | Singleton renaming environment for the given namespace.+singletonNS :: Namespace -> PName -> Name -> NamingEnv+singletonNS ns pn n = NamingEnv (Map.singleton ns (Map.singleton pn (One n))) -- | Generate a mapping from 'PrimIdent' to 'Name' for a -- given naming environment.@@ -124,7 +131,8 @@ } where fromNS ns = Map.fromList- [ entry x | xs <- Map.elems (namespaceMap ns env), x <- xs ]+ [ entry x | xs <- Map.elems (namespaceMap ns env)+ , x <- namesToList xs ] entry n = case asPrim n of Just p -> (p,n)@@ -139,9 +147,9 @@ where names = Map.fromList [ (og, qn)- | ns <- [ NSValue, NSType, NSModule ]+ | ns <- allNamespaces , (pn,xs) <- Map.toList (namespaceMap ns env)- , x <- xs+ , x <- namesToList xs , og <- maybeToList (asOrigName x) , let qn = case getModName pn of Just q -> Qualified q@@ -154,145 +162,127 @@ -- NOTE: if entries in the NamingEnv would have produced a name clash, -- they will be omitted from the resulting sets. visibleNames :: NamingEnv -> Map Namespace (Set Name)-visibleNames (NamingEnv env) = Set.fromList . mapMaybe check . Map.elems <$> env- where- check names =- case names of- [name] -> Just name- _ -> Nothing+visibleNames (NamingEnv env) = check <$> env+ where check mp = Set.fromList [ a | One a <- Map.elems mp ] -- | Qualify all symbols in a 'NamingEnv' with the given prefix. qualify :: ModName -> NamingEnv -> NamingEnv qualify pfx (NamingEnv env) = NamingEnv (Map.mapKeys toQual <$> env) where- -- XXX we don't currently qualify fresh names+ -- We don't qualify fresh names, because they should not be directly+ -- visible to the end users (i.e., they shouldn't really be exported) toQual (Qual _ n) = Qual pfx n toQual (UnQual n) = Qual pfx n toQual n@NewName{} = n -filterNames :: (PName -> Bool) -> NamingEnv -> NamingEnv-filterNames p (NamingEnv env) = NamingEnv (Map.filterWithKey check <$> env)- where check n _ = p n----- | Like mappend, but when merging, prefer values on the lhs.-shadowing :: NamingEnv -> NamingEnv -> NamingEnv-shadowing (NamingEnv l) (NamingEnv r) = NamingEnv (Map.unionWith Map.union l r)+filterPNames :: (PName -> Bool) -> NamingEnv -> NamingEnv+filterPNames p (NamingEnv env) = NamingEnv (Map.mapMaybe checkNS env)+ where+ checkNS nsMap = let new = Map.filterWithKey (\n _ -> p n) nsMap+ in if Map.null new then Nothing else Just new -travNamingEnv :: Applicative f => (Name -> f Name) -> NamingEnv -> f NamingEnv-travNamingEnv f (NamingEnv mp) =- NamingEnv <$> traverse (traverse (traverse f)) mp+filterUNames :: (Name -> Bool) -> NamingEnv -> NamingEnv+filterUNames p (NamingEnv env) = NamingEnv (Map.mapMaybe check env)+ where+ check nsMap = let new = Map.mapMaybe (filterNames p) nsMap+ in if Map.null new then Nothing else Just new -{- | Do somethign in context. If `Nothing` than we are working with-a local declaration. Otherwise we are at the top-level of the-given module. -}-data InModule a = InModule (Maybe ModPath) a- deriving (Functor,Traversable,Foldable,Show)-+-- | Find the ambiguous entries in an environmet.+-- A name is ambiguous if it might refer to multiple entities.+findAmbig :: NamingEnv -> [ [Name] ]+findAmbig (NamingEnv ns) =+ [ Set.toList xs+ | mp <- Map.elems ns+ , Ambig xs <- Map.elems mp+ ] -newTop ::- FreshM m => Namespace -> ModPath -> PName -> Maybe Fixity -> Range -> m Name-newTop ns m thing fx rng =- liftSupply (mkDeclared ns m src (getIdent thing) fx rng)- where src = if isGeneratedName thing then SystemName else UserName+-- | Get the subset of the first environment that shadows something+-- in the second one.+findShadowing :: NamingEnv -> NamingEnv -> [ (PName,Name,[Name]) ]+findShadowing (NamingEnv lhs) rhs =+ [ (p, anyOne xs, namesToList ys)+ | (ns,mp) <- Map.toList lhs+ , (p,xs) <- Map.toList mp+ , Just ys <- [ lookupNS ns p rhs ]+ ] -newLocal :: FreshM m => Namespace -> PName -> Range -> m Name-newLocal ns thing rng = liftSupply (mkParameter ns (getIdent thing) rng)+-- | Do an arbitrary choice for ambiguous names.+-- We do this to continue checking afetr we've reported an ambiguity error.+forceUnambig :: NamingEnv -> NamingEnv+forceUnambig (NamingEnv mp) = NamingEnv (fmap (One . anyOne) <$> mp) -newtype BuildNamingEnv = BuildNamingEnv { runBuild :: SupplyT Id NamingEnv }+-- | Like mappend, but when merging, prefer values on the lhs.+shadowing :: NamingEnv -> NamingEnv -> NamingEnv+shadowing (NamingEnv l) (NamingEnv r) = NamingEnv (Map.unionWith Map.union l r) +mapNamingEnv :: (Name -> Name) -> NamingEnv -> NamingEnv+mapNamingEnv f (NamingEnv mp) = NamingEnv (fmap (mapNames f) <$> mp) -buildNamingEnv :: BuildNamingEnv -> Supply -> (NamingEnv,Supply)-buildNamingEnv b supply = runId $ runSupplyT supply $ runBuild b+travNamingEnv :: Applicative f => (Name -> f Name) -> NamingEnv -> f NamingEnv+travNamingEnv f (NamingEnv mp) =+ NamingEnv <$> traverse (traverse (travNames f)) mp --- | Generate a 'NamingEnv' using an explicit supply.-defsOf :: BindsNames a => a -> Supply -> (NamingEnv,Supply)-defsOf = buildNamingEnv . namingEnv+isEmptyNamingEnv :: NamingEnv -> Bool+isEmptyNamingEnv (NamingEnv mp) = Map.null mp+-- This assumes that we've been normalizing away empty maps, hopefully+-- we've been doing it everywhere. ------------------------------------------------------------------------------------ Collect definitions of nested modules--type NestedMods = Map Name NamingEnv-type CollectM = StateT NestedMods (SupplyT Id)--collectNestedModules ::- NamingEnv -> Module PName -> Supply -> (NestedMods, Supply)-collectNestedModules env m =- collectNestedModulesDecls env (thing (mName m)) (mDecls m)--collectNestedModulesDecls ::- NamingEnv -> ModName -> [TopDecl PName] -> Supply -> (NestedMods, Supply)-collectNestedModulesDecls env m ds sup = (mp,newS)+-- | Compute an unqualified naming environment, containing the various module+-- parameters.+modParamsNamingEnv :: T.ModParamNames -> NamingEnv+modParamsNamingEnv T.ModParamNames { .. } =+ NamingEnv $ Map.fromList+ [ (NSValue, Map.fromList $ map fromFu $ Map.keys mpnFuns)+ , (NSType, Map.fromList $ map fromTS (Map.elems mpnTySyn) +++ map fromTy (Map.elems mpnTypes))+ ] where- s0 = Map.empty- mpath = TopModule m- ((_,mp),newS) = runId $ runSupplyT sup $ runStateT s0 $- collectNestedModulesDs mpath env ds--collectNestedModulesDs :: ModPath -> NamingEnv -> [TopDecl PName] -> CollectM ()-collectNestedModulesDs mpath env ds =- forM_ [ tlValue nm | DModule nm <- ds ] \(NestedModule nested) ->- do let pname = thing (mName nested)- name = case lookupNS NSModule pname env of- n : _ -> n -- if a name is ambiguous we may get- -- multiple answers, but we just pick one.- -- This should be OK, as the error should be- -- caught during actual renaming.- _ -> panic "collectedNestedModulesDs"- [ "Missing definition for " ++ show pname ]- newEnv <- lift (runBuild (moduleDefs (Nested mpath (nameIdent name)) nested))- sets_ (Map.insert name newEnv)- let newMPath = Nested mpath (nameIdent name)- collectNestedModulesDs newMPath newEnv (mDecls nested)+ toPName n = mkUnqual (nameIdent n) ---------------------------------------------------------------------------------+ fromTy tp = let nm = T.mtpName tp+ in (toPName nm, One nm) + fromFu f = (toPName f, One f) + fromTS ts = (toPName (T.tsName ts), One (T.tsName ts)) -instance Semigroup BuildNamingEnv where- BuildNamingEnv a <> BuildNamingEnv b = BuildNamingEnv $- do x <- a- y <- b- return (mappend x y)--instance Monoid BuildNamingEnv where- mempty = BuildNamingEnv (pure mempty)-- mappend = (<>)-- mconcat bs = BuildNamingEnv $- do ns <- sequence (map runBuild bs)- return (mconcat ns)-----------------------------------------------------------------------------------+-- | Generate a naming environment from a declaration interface, where none of+-- the names are qualified.+unqualifiedEnv :: IfaceDecls -> NamingEnv+unqualifiedEnv IfaceDecls { .. } =+ mconcat [ exprs, tySyns, ntTypes, absTys, ntExprs, mods, sigs ]+ where+ toPName n = mkUnqual (nameIdent n) + exprs = mconcat [ singletonNS NSValue (toPName n) n+ | n <- Map.keys ifDecls ] --- | Things that define exported names.-class BindsNames a where- namingEnv :: a -> BuildNamingEnv+ tySyns = mconcat [ singletonNS NSType (toPName n) n+ | n <- Map.keys ifTySyns ] -instance BindsNames NamingEnv where- namingEnv env = BuildNamingEnv (return env)- {-# INLINE namingEnv #-}+ ntTypes = mconcat [ n+ | nt <- Map.elems ifNewtypes+ , let tname = T.ntName nt+ cname = T.ntConName nt+ , n <- [ singletonNS NSType (toPName tname) tname+ , singletonNS NSValue (toPName cname) cname+ ]+ ] -instance BindsNames a => BindsNames (Maybe a) where- namingEnv = foldMap namingEnv- {-# INLINE namingEnv #-}+ absTys = mconcat [ singletonNS NSType (toPName n) n+ | n <- Map.keys ifAbstractTypes ] -instance BindsNames a => BindsNames [a] where- namingEnv = foldMap namingEnv- {-# INLINE namingEnv #-}+ ntExprs = mconcat [ singletonNS NSValue (toPName n) n+ | n <- Map.keys ifNewtypes ] --- | Generate a type renaming environment from the parameters that are bound by--- this schema.-instance BindsNames (Schema PName) where- namingEnv (Forall ps _ _ _) = foldMap namingEnv ps- {-# INLINE namingEnv #-}+ mods = mconcat [ singletonNS NSModule (toPName n) n+ | n <- Map.keys ifModules ] + sigs = mconcat [ singletonNS NSModule (toPName n) n+ | n <- Map.keys ifSignatures ] -- | Adapt the things exported by something to the specific import/open.@@ -309,166 +299,12 @@ -- restrict or hide imported symbols restricted | Just (Hiding ns) <- iSpec imp =- filterNames (\qn -> not (getIdent qn `elem` ns)) public+ filterPNames (\qn -> not (getIdent qn `elem` ns)) public | Just (Only ns) <- iSpec imp =- filterNames (\qn -> getIdent qn `elem` ns) public+ filterPNames (\qn -> getIdent qn `elem` ns) public | otherwise = public --- | Interpret an import in the context of an interface, to produce a name--- environment for the renamer, and a 'NameDisp' for pretty-printing.-interpImportIface :: Import {- ^ The import declarations -} ->- IfaceDecls {- ^ Declarations of imported module -} ->- NamingEnv-interpImportIface imp = interpImportEnv imp . unqualifiedEnv----- | Generate a naming environment from a declaration interface, where none of--- the names are qualified.-unqualifiedEnv :: IfaceDecls -> NamingEnv-unqualifiedEnv IfaceDecls { .. } =- mconcat [ exprs, tySyns, ntTypes, absTys, ntExprs, mods ]- where- toPName n = mkUnqual (nameIdent n)-- exprs = mconcat [ singletonE (toPName n) n | n <- Map.keys ifDecls ]- tySyns = mconcat [ singletonT (toPName n) n | n <- Map.keys ifTySyns ]- ntTypes = mconcat [ singletonT (toPName n) n | n <- Map.keys ifNewtypes ]- absTys = mconcat [ singletonT (toPName n) n | n <- Map.keys ifAbstractTypes ]- ntExprs = mconcat [ singletonE (toPName n) n | n <- Map.keys ifNewtypes ]- mods = mconcat [ singletonNS NSModule (toPName n) n- | n <- Map.keys ifModules ]---- | Compute an unqualified naming environment, containing the various module--- parameters.-modParamsNamingEnv :: IfaceParams -> NamingEnv-modParamsNamingEnv IfaceParams { .. } =- NamingEnv $ Map.fromList- [ (NSValue, Map.fromList $ map fromFu $ Map.keys ifParamFuns)- , (NSType, Map.fromList $ map fromTy $ Map.elems ifParamTypes)- ]- where- toPName n = mkUnqual (nameIdent n)-- fromTy tp = let nm = T.mtpName tp- in (toPName nm, [nm])-- fromFu f = (toPName f, [f])----data ImportIface = ImportIface Import Iface---- | Produce a naming environment from an interface file, that contains a--- mapping only from unqualified names to qualified ones.-instance BindsNames ImportIface where- namingEnv (ImportIface imp Iface { .. }) = BuildNamingEnv $- return (interpImportIface imp ifPublic)- {-# INLINE namingEnv #-}---- | Introduce the name-instance BindsNames (InModule (Bind PName)) where- namingEnv (InModule mb b) = BuildNamingEnv $- do let Located { .. } = bName b- n <- case mb of- Just m -> newTop NSValue m thing (bFixity b) srcRange- Nothing -> newLocal NSValue thing srcRange -- local fixitiies?-- return (singletonE thing n)---- | Generate the naming environment for a type parameter.-instance BindsNames (TParam PName) where- namingEnv TParam { .. } = BuildNamingEnv $- do let range = fromMaybe emptyRange tpRange- n <- newLocal NSType tpName range- return (singletonT tpName n)---- | The naming environment for a single module. This is the mapping from--- unqualified names to fully qualified names with uniques.-instance BindsNames (Module PName) where- namingEnv m = moduleDefs (TopModule (thing (mName m))) m---moduleDefs :: ModPath -> ModuleG mname PName -> BuildNamingEnv-moduleDefs m Module { .. } = foldMap (namingEnv . InModule (Just m)) mDecls---instance BindsNames (InModule (TopDecl PName)) where- namingEnv (InModule ns td) =- case td of- Decl d -> namingEnv (InModule ns (tlValue d))- DPrimType d -> namingEnv (InModule ns (tlValue d))- TDNewtype d -> namingEnv (InModule ns (tlValue d))- DParameterType d -> namingEnv (InModule ns d)- DParameterConstraint {} -> mempty- DParameterFun d -> namingEnv (InModule ns d)- Include _ -> mempty- DImport {} -> mempty -- see 'openLoop' in the renamer- DModule m -> namingEnv (InModule ns (tlValue m))---instance BindsNames (InModule (NestedModule PName)) where- namingEnv (InModule ~(Just m) (NestedModule mdef)) = BuildNamingEnv $- 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 { .. }) =- BuildNamingEnv $- do let Located { .. } = primTName- nm <- newTop NSType m thing primTFixity srcRange- pure (singletonT thing nm)--instance BindsNames (InModule (ParameterFun PName)) where- namingEnv (InModule ~(Just ns) ParameterFun { .. }) = BuildNamingEnv $- do let Located { .. } = pfName- ntName <- newTop NSValue ns thing pfFixity srcRange- return (singletonE thing ntName)--instance BindsNames (InModule (ParameterType PName)) where- namingEnv (InModule ~(Just ns) ParameterType { .. }) = BuildNamingEnv $- -- 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 (singletonT thing ntName)---- NOTE: we use the same name at the type and expression level, as there's only--- ever one name introduced in the declaration. The names are only ever used in--- different namespaces, so there's no ambiguity.-instance BindsNames (InModule (Newtype PName)) where- namingEnv (InModule ~(Just ns) Newtype { .. }) = BuildNamingEnv $- do let Located { .. } = nName- ntName <- newTop NSType ns thing Nothing srcRange- -- XXX: the name reuse here is sketchy- return (singletonT thing ntName `mappend` singletonE thing ntName)---- | The naming environment for a single declaration.-instance BindsNames (InModule (Decl PName)) where- namingEnv (InModule pfx d) = case d of- DBind b -> namingEnv (InModule pfx b)- DSignature ns _sig -> foldMap qualBind ns- DPragma ns _p -> foldMap qualBind ns- DType syn -> qualType (tsName syn) (tsFixity syn)- DProp syn -> qualType (psName syn) (psFixity syn)- DLocated d' _ -> namingEnv (InModule pfx d')- DRec {} -> panic "namingEnv" [ "DRec" ]- DPatBind _pat _e -> panic "namingEnv" ["Unexpected pattern binding"]- DFixity{} -> panic "namingEnv" ["Unexpected fixity declaration"]-- where-- mkName ns ln fx = case pfx of- Just m -> newTop ns m (thing ln) fx (srcRange ln)- Nothing -> newLocal ns (thing ln) (srcRange ln)-- qualBind ln = BuildNamingEnv $- do n <- mkName NSValue ln Nothing- return (singletonE (thing ln) n)-- qualType ln f = BuildNamingEnv $- do n <- mkName NSType ln f- return (singletonT (thing ln) n)
src/Cryptol/ModuleSystem/Renamer.hs view
@@ -10,9 +10,10 @@ {-# Language FlexibleInstances #-} {-# Language FlexibleContexts #-} {-# Language BlockArguments #-}+{-# Language OverloadedStrings #-} module Cryptol.ModuleSystem.Renamer ( NamingEnv(), shadowing- , BindsNames(..), InModule(..)+ , BindsNames, InModule(..) , shadowNames , Rename(..), runRenamer, RenameM() , RenamerError(..)@@ -30,154 +31,301 @@ import Prelude.Compat import Data.Either(partitionEithers)-import Data.Maybe(fromJust)-import Data.List(find,foldl')+import Data.Maybe(mapMaybe)+import Data.List(find,groupBy,sortBy)+import Data.Function(on) import Data.Foldable(toList)-import Data.Map.Strict(Map)+import Data.Map(Map) import qualified Data.Map.Strict as Map import qualified Data.Set as Set import Data.Graph(SCC(..)) import Data.Graph.SCC(stronglyConnComp)-import MonadLib hiding (mapM, mapM_)+import MonadLib hiding (mapM, mapM_) import Cryptol.ModuleSystem.Name+import Cryptol.ModuleSystem.Names import Cryptol.ModuleSystem.NamingEnv import Cryptol.ModuleSystem.Exports-import Cryptol.Parser.Position(getLoc)+import Cryptol.Parser.Position(Range) import Cryptol.Parser.AST import Cryptol.Parser.Selector(selName) import Cryptol.Utils.Panic (panic) import Cryptol.Utils.RecordMap-import Cryptol.Utils.Ident(allNamespaces,packModName)+import Cryptol.Utils.Ident(allNamespaces,OrigName(..),modPathCommon,+ undefinedModName)+import Cryptol.Utils.PP import Cryptol.ModuleSystem.Interface import Cryptol.ModuleSystem.Renamer.Error+import Cryptol.ModuleSystem.Binds import Cryptol.ModuleSystem.Renamer.Monad+import Cryptol.ModuleSystem.Renamer.Imports+import Cryptol.ModuleSystem.Renamer.ImplicitImports +{-+The Renamer Algorithm+=====================++1. Add implicit imports for visible nested modules++2. Compute what each module defines (see "Cryptol.ModuleSystem.Binds")+ - This assigns unique names to names introduces by various declarations+ - Here we detect repeated top-level definitions in a module.+ - Module instantiations also get a name, but are not yet resolved, so+ we don't know what's defined by them.+ - We do not generate unique names for functor parameters---those will+ be matched textually to the arguments when applied.+ - We *do* generate unique names for declarations in "signatures"+ * those are only really needed when renaming the signature (step 4)+ (e.g., to determine if a name refers to something declared in the+ signature or something else).+ * when validating a module against a signature the names of the declarations+ are matched textually, *not* using the unique names+ (e.g., `x` in a signature is matched with the thing named `x` in a module,+ even though these two `x`s will have different unique `id`s)+++3. Resolve imports and instantiations (see "Cryptol.ModuleSystem.Imports")+ - Resolves names in submodule imports+ - Resolves functor instantiations:+ * generate new names for declarations in the functors.+ * this includes any nested modules, and things nested within them.+ - At this point we have enough information to know what's exported by+ each module.++4. Do the renaming (this module)+ - Using step 3 we compute the scoping environment for each module/signature+ - We traverse all declarations and replace the parser names with the+ corresponding names in scope:+ * Here we detect ambiguity and undefined errors+ * During this pass is also where we keep track of information of what+ names are used by declarations:+ - this is used to compute the dependencies between declarations+ - which are in turn used to order the declarations in dependency order+ * this is assumed by the TC+ * here we also report errors about invalid recursive dependencies+ * During this stage we also issue warning about unused type names+ (and we should probably do unused value names too one day)+ - During the rewriting we also do:+ - rebalance expression trees using the operator fixities+ - desugar record update notation+-}+++-- | The result of renaming a module 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+ , rmImported :: IfaceDecls+ -- ^ Imported declarations. This provides the types for external+ -- names (used by the type-checker). } +-- | Entry point. This is used for renaming a top-level module. renameModule :: Module PName -> RenameM RenamedModule renameModule m0 =- do let m = m0 { mDecls = snd (addImplicitNestedImports (mDecls m0)) }- env <- liftSupply (defsOf m)- nested <- liftSupply (collectNestedModules env m)- setNestedModule (nestedModuleNames nested)- do (ifs,(inScope,m1)) <- collectIfaceDeps- $ renameModule' nested env (TopModule (thing (mName m))) m+ do -- Step 1: add implicit imports+ let m = m0 { mDef =+ case mDef m0 of+ NormalModule ds ->+ NormalModule (addImplicitNestedImports ds)+ FunctorInstance f as i -> FunctorInstance f as i+ InterfaceModule s -> InterfaceModule s+ }++ -- Step 2: compute what's defined+ (defs,errs) <- liftSupply (modBuilder (topModuleDefs m))+ mapM_ recordError errs++ -- Step 3: resolve imports+ extern <- getExternal+ resolvedMods <- liftSupply (resolveImports extern defs)++ let pathToName = Map.fromList [ (Nested (nameModPath x) (nameIdent x), x)+ | ImpNested x <- Map.keys resolvedMods ]+++ let mname = ImpTop (thing (mName m))++ setResolvedLocals resolvedMods $+ setNestedModule pathToName+ do (ifs,(inScope,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?+ -- XXX: maybe we should keep the nested defines too? } +++++{- | Entry point. Rename a list of top-level declarations.+This is used for declaration that don't live in a module+(e.g., define on the command line.)++We assume that these declarations do not contain any nested modules.+-} renameTopDecls :: ModName -> [TopDecl PName] -> RenameM (NamingEnv,[TopDecl Name]) renameTopDecls m ds0 =- do let ds = snd (addImplicitNestedImports ds0)- let mpath = TopModule m- env <- liftSupply (defsOf (map (InModule (Just mpath)) ds))- nested <- liftSupply (collectNestedModulesDecls env m ds) - setNestedModule (nestedModuleNames nested)- do ds1 <- shadowNames' CheckOverlap env- (renameTopDecls' (nested,mpath) ds)- -- record a use of top-level names to avoid- -- unused name warnings- let exports = concatMap exportedNames ds1- mapM_ recordUse (foldMap (exported NSType) exports)+ do -- Step 1: add implicit imports+ let ds = addImplicitNestedImports ds0 - pure (env,ds1)+ -- Step 2: compute what's defined+ (defs,errs) <- liftSupply (modBuilder (topDeclsDefs (TopModule m) ds))+ mapM_ recordError errs --- | Returns declarations with additional imports and the public module names--- of this module and its children-addImplicitNestedImports ::- [TopDecl PName] -> ([[Ident]], [TopDecl PName])-addImplicitNestedImports decls = (concat exportedMods, concat newDecls ++ other)- where- (mods,other) = foldr classify ([], []) decls- (newDecls,exportedMods) = unzip (map processModule mods)- processModule m =- let NestedModule m1 = tlValue m- (childExs, ds1) = addImplicitNestedImports (mDecls m1)- mname = getIdent (thing (mName m1))- imps = map (mname :) ([] : childExs)- isToName is = case is of- [i] -> mkUnqual i- _ -> mkQual (isToQual (init is)) (last is)- isToQual is = packModName (map identText is)- mkImp xs = DImport- Located- { srcRange = srcRange (mName m1)- , thing = Import- { iModule = ImpNested (isToName xs)- , iAs = Just (isToQual xs)- , iSpec = Nothing- }- }- in ( DModule m { tlValue = NestedModule m1 { mDecls = ds1 } }- : map mkImp imps- , case tlExport m of- Public -> imps- Private -> []- )+ -- Step 3: resolve imports+ extern <- getExternal+ resolvedMods <- liftSupply (resolveImports extern (TopMod m defs)) + let pathToName = Map.fromList [ (Nested (nameModPath x) (nameIdent x), x)+ | ImpNested x <- Map.keys resolvedMods ] - classify d (ms,ds) =- case d of- DModule tl -> (tl : ms, ds)- _ -> (ms, d : ds) + setResolvedLocals resolvedMods $+ setNestedModule pathToName+ do env <- rmodDefines <$> lookupResolved (ImpTop m) -nestedModuleNames :: NestedMods -> Map ModPath Name-nestedModuleNames mp = Map.fromList (map entry (Map.keys mp))- where- entry n = case nameInfo n of- Declared p _ -> (Nested p (nameIdent n),n)- _ -> panic "nestedModuleName" [ "Not a top-level name" ]+ -- we already checked for duplicates in Step 2+ ds1 <- shadowNames' CheckNone env (renameTopDecls' ds)+ -- record a use of top-level names to avoid+ -- unused name warnings+ let exports = exportedDecls ds1+ mapM_ recordUse (exported NSType exports) + pure (env,ds1) +--------------------------------------------------------------------------------+-- Stuff below is related to Step 4 of the algorithm.++ class Rename f where rename :: f PName -> RenameM (f Name) --- | Returns:+-- | This is used for both top-level and nested modules.+-- Returns: ----- * Interfaces for imported things,--- * Things defines in the module+-- * Things defined in the module -- * Renamed module renameModule' ::- NestedMods -> NamingEnv -> ModPath -> ModuleG mname PName ->+ ImpName Name {- ^ Resolved name for this module -} ->+ ModuleG mname PName -> RenameM (NamingEnv, ModuleG mname Name)-renameModule' thisNested env mpath m =- setCurMod mpath- do (moreNested,imps) <- mconcat <$> mapM doImport (mImports m)- let allNested = Map.union moreNested thisNested- openDs = map thing (mSubmoduleImports m)- allImps = openLoop allNested env openDs imps+renameModule' mname m =+ setCurMod+ case mname of+ ImpTop r -> TopModule r+ ImpNested r -> Nested (nameModPath r) (nameIdent r) - (inScope,decls') <-- shadowNames' CheckNone allImps $- shadowNames' CheckOverlap env $- -- maybe we should allow for a warning- -- if a local name shadows an imported one?- do inScope <- getNamingEnv- ds <- renameTopDecls' (allNested,mpath) (mDecls m)- pure (inScope, ds)- let m1 = m { mDecls = decls' }- exports = modExports m1- mapM_ recordUse (exported NSType exports)- return (inScope, m1)+ do resolved <- lookupResolved mname+ shadowNames' CheckNone (rmodImports resolved) + case mDef m of + NormalModule ds ->+ do let env = rmodDefines resolved+ (paramEnv,params) <-+ shadowNames' CheckNone env+ (doModParams (mModParams m))++ -- we check that defined names and ones that came+ -- from parameters do not clash, as this would be+ -- very confusing.+ shadowNames' CheckOverlap (env <> paramEnv) $+ setModParams params+ do ds1 <- renameTopDecls' ds+ let exports = exportedDecls ds1+ mapM_ recordUse (exported NSType exports)+ inScope <- getNamingEnv+ pure (inScope, m { mDef = NormalModule ds1 })++ -- The things defined by this module are the *results*+ -- of the instantiation, so we should *not* add them+ -- in scope when resolving.+ FunctorInstance f as _ ->+ do f' <- rnLocated rename f+ as' <- rename as+ checkFunctorArgs as'++ 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 })++ InterfaceModule s ->+ shadowNames' CheckNone (rmodDefines resolved)+ do d <- InterfaceModule <$> renameIfaceModule mname s+ inScope <- getNamingEnv+ pure (inScope, m { mDef = d })+++checkFunctorArgs :: ModuleInstanceArgs Name -> RenameM ()+checkFunctorArgs args =+ case args of+ DefaultInstAnonArg {} ->+ panic "checkFunctorArgs" ["Nested DefaultInstAnonArg"]+ DefaultInstArg l -> checkArg l+ NamedInstArgs as -> mapM_ checkNamedArg as+ where+ checkNamedArg (ModuleInstanceNamedArg _ l) = checkArg l++ checkArg l =+ case thing l of+ ModuleArg m+ | isFakeName m -> pure ()+ | otherwise -> checkIsModule (srcRange l) m AModule+ ParameterArg {} -> pure () -- we check these in the type checker+ AddParams -> pure ()++mkInstMap :: Maybe Range -> Map Name Name -> ImpName Name -> ImpName Name ->+ RenameM (Map Name Name)+mkInstMap checkFun acc0 ogname iname+ | isFakeName ogname = pure Map.empty+ | otherwise =+ do case checkFun of+ Nothing -> pure ()+ Just r -> checkIsModule r ogname AFunctor+ (onames,osubs) <- lookupDefinesAndSubs ogname+ inames <- lookupDefines iname+ let mp = zipByTextName onames inames+ subs = [ (ImpNested k, ImpNested v)+ | k <- Set.toList osubs, Just v <- [Map.lookup k mp]+ ]+ foldM doSub (Map.union mp acc0) subs++ where+ doSub acc (k,v) = mkInstMap Nothing acc k v++++-- | This is used to rename local declarations (e.g. `where`) renameDecls :: [Decl PName] -> RenameM [Decl Name] renameDecls ds = do (ds1,deps) <- depGroup (traverse rename ds)@@ -192,14 +340,37 @@ CyclicSCC ds_xs -> let (rds,xs) = unzip ds_xs in case mapM validRecursiveD rds of- Nothing -> do record (InvalidDependency xs)+ Nothing -> do recordError (InvalidDependency xs) pure rds Just bs -> do checkSameModule xs pure [DRec bs] concat <$> mapM fromSCC ordered +-- | Rename declarations in a signature (i.e., type/prop synonyms)+renameSigDecls :: [SigDecl PName] -> RenameM [SigDecl Name]+renameSigDecls ds =+ do (ds1,deps) <- depGroup (traverse rename ds)+ let toNode d = let nm = case d of+ SigTySyn ts _ -> thing (tsName ts)+ SigPropSyn ps _ -> thing (psName ps)+ x = NamedThing nm+ in ((d,x), x, map NamedThing+ $ Set.toList+ $ Map.findWithDefault Set.empty x deps)+ ordered = toList (stronglyConnComp (map toNode ds1))+ fromSCC x =+ case x of+ AcyclicSCC (d,_) -> pure [d]+ CyclicSCC ds_xs ->+ do let (rds,xs) = unzip ds_xs+ recordError (InvalidDependency xs)+ pure rds + concat <$> mapM fromSCC ordered+++ validRecursiveD :: Decl name -> Maybe (Bind name) validRecursiveD d = case d of@@ -212,24 +383,128 @@ case ms of a : as | let bad = [ fst b | b <- as, snd a /= snd b ] , not (null bad) ->- record $ InvalidDependency $ map NamedThing $ fst a : bad+ recordError (InvalidDependency $ map NamedThing $ fst a : bad) _ -> pure () where- ms = [ (x,p) | NamedThing x <- xs, Declared p _ <- [ nameInfo x ] ]+ ms = [ (x,ogModule og)+ | NamedThing x <- xs, GlobalName _ og <- [ nameInfo x ]+ ] -renameTopDecls' ::- (NestedMods,ModPath) -> [TopDecl PName] -> RenameM [TopDecl Name]-renameTopDecls' info ds =- do (ds1,deps) <- depGroup (traverse (renameWithMods info) ds) +{- NOTE: Dependencies on Top Level Constraints+ =========================================== - let (noNameDs,nameDs) = partitionEithers (map topDeclName ds1)- ctrs = [ nm | (_,nm@(ConstratintAt {})) <- nameDs ]- toNode (d,x) = ((d,x),x, (if usesCtrs d then ctrs else []) ++- map NamedThing- ( Set.toList- ( Map.findWithDefault Set.empty x deps) ))+For the new module system, things using a parameter depend on the parameter+declaration (i.e., `import signature`), which depends on the signature,+so dependencies on constraints in there should be OK.++However, we'd like to have a mechanism for declaring top level constraints in+a functor, that can impose constraints across types from *different*+parameters. For the moment, we reuse `parameter type constraint C` for this.++Such constraints need to be:+ 1. After the signature import+ 2. After any type synonyms/newtypes using the parameters+ 3. Before any value or type declarations that need to use the parameters.++Note that type declarations used by a constraint cannot use the constraint,+so they need to be well formed without it.++For other types, we use the following rule to determine if they use a+constraint:++ If:+ 1. We have a constraint and type declaration+ 2. They both mention the same type parameter+ 3. There is no explicit dependency of the constraint on the DECL+ Then:+ The type declaration depends on the constraint.++Example:++ type T = 10 // Does not depend on anything so can go first++ signature A where+ type n : #++ import signature A // Depends on A, so need to be after A++ parameter type constraint n > T+ // Depends on the import (for @n@) and T++ type Q = [n-T] // Depends on the top-level constraint+-}++++-- This assumes imports have already been processed+renameTopDecls' :: [TopDecl PName] -> RenameM [TopDecl Name]+renameTopDecls' ds =+ do -- rename and compute what names we depend on+ (ds1,deps) <- depGroup (traverse rename ds)++ fromParams <- getNamesFromModParams+ localParams <- getLocalModParamDeps++ let rawDepsFor x = Map.findWithDefault Set.empty x deps++ isTyParam x = nameNamespace x == NSType && x `Map.member` fromParams+++ (noNameDs,nameDs) = partitionEithers (map topDeclName ds1)+ ctrs = [ nm | (_,nm@(ConstratintAt {}),_) <- nameDs ]+ indirect = Map.fromList [ (y,x)+ | (_,x,ys) <- nameDs, y <- ys ]+ mkDepName x = case Map.lookup x fromParams of+ Just dn -> dn+ Nothing -> NamedThing x+ depsFor x =+ [ Map.findWithDefault (mkDepName y) (NamedThing y) indirect+ | y <- Set.toList (Map.findWithDefault Set.empty x deps)+ ]++ {- See [NOTE: Dependencies on Top Level Constraints] -}+ addCtr nm ctr =+ case nm of+ NamedThing x+ | nameNamespace x == NSType+ , let ctrDeps = rawDepsFor ctr+ tyDeps = rawDepsFor nm+ , not (x `Set.member` ctrDeps)+ , not (Set.null (Set.intersection+ (Set.filter isTyParam ctrDeps)+ (Set.filter isTyParam tyDeps)))+ -> Just ctr+ _ -> Nothing++ addCtrs (d,x)+ | usesCtrs d = ctrs+ | otherwise = mapMaybe (addCtr x) ctrs++ addModParams d =+ case d of+ DModule tl | NestedModule m <- tlValue tl+ , FunctorInstance _ as _ <- mDef m ->+ case as of+ DefaultInstArg arg -> depsOfArg arg+ NamedInstArgs args -> concatMap depsOfNamedArg args+ DefaultInstAnonArg {} -> []++ where depsOfNamedArg (ModuleInstanceNamedArg _ a) = depsOfArg a+ depsOfArg a = case thing a of+ AddParams -> []+ ModuleArg {} -> []+ ParameterArg p ->+ case Map.lookup p localParams of+ Just i -> [i]+ Nothing -> []+ _ -> []++ toNode (d,x,_) = ((d,x),x, addCtrs (d,x) +++ addModParams d +++ depsFor x)+ ordered = stronglyConnComp (map toNode nameDs) fromSCC x = case x of@@ -237,7 +512,7 @@ CyclicSCC ds_xs -> let (rds,xs) = unzip ds_xs in case mapM valid rds of- Nothing -> do record (InvalidDependency xs)+ Nothing -> do recordError (InvalidDependency xs) pure rds Just bs -> do checkSameModule xs@@ -253,36 +528,49 @@ rds <- mapM fromSCC ordered pure (concat (noNameDs:rds)) where++ -- This indicates if a declaration might depend on the constraints in scope.+ -- Since uses of constraints are not implicitly named, value declarations+ -- are assumed to potentially use the constraints.++ -- XXX: This is inaccurate, and *I think* it amounts to checking that something+ -- is in the value namespace. Perhaps the rule should be that a value+ -- depends on a parameter constraint if it mentions at least one+ -- type parameter somewhere.++ -- XXX: Besides, types might need constraints for well-formedness...+ -- This is just bogus+ -- Although not that type/prop synonyms may be defined wherever as they+ -- keep the validity constraints they need and emit them at the *use* sites. usesCtrs td = case td of Decl tl -> isValDecl (tlValue tl) DPrimType {} -> False TDNewtype {} -> False- DParameterType {} -> False- DParameterConstraint {} -> False-- DParameterFun {} -> True- -- Here we may need the constraints to validate the type- -- (e.g., if the parameter is of type `Z a`)+ DParamDecl {} -> False+ DInterfaceConstraint {} -> False DModule tl -> any usesCtrs (mDecls m) where NestedModule m = tlValue tl DImport {} -> False+ DModParam {} -> False -- no definitions here Include {} -> bad "Include" isValDecl d = case d of DLocated d' _ -> isValDecl d' DBind {} -> True+ DRec {} -> True+ DType {} -> False DProp {} -> False- DRec {} -> True- DSignature {} -> bad "DSignature"- DFixity {} -> bad "DFixity"- DPragma {} -> bad "DPragma"- DPatBind {} -> bad "DPatBind" + DSignature {} -> bad "DSignature"+ DFixity {} -> bad "DFixity"+ DPragma {} -> bad "DPragma"+ DPatBind {} -> bad "DPatBind"+ bad msg = panic "renameTopDecls'" [msg] @@ -302,172 +590,243 @@ where bad x = panic "declName" [x] -topDeclName :: TopDecl Name -> Either (TopDecl Name) (TopDecl Name, DepName)+topDeclName ::+ TopDecl Name ->+ Either (TopDecl Name) (TopDecl Name, DepName, [DepName]) topDeclName topDecl = case topDecl of Decl d -> hasName (declName (tlValue d)) DPrimType d -> hasName (thing (primTName (tlValue d)))- TDNewtype d -> hasName (thing (nName (tlValue d)))- DParameterType d -> hasName (thing (ptName d))- DParameterFun d -> hasName (thing (pfName d))+ TDNewtype d -> hasName' (thing (nName (tlValue d)))+ [ nConName (tlValue d) ] DModule d -> hasName (thing (mName m)) where NestedModule m = tlValue d - DParameterConstraint ds ->- case ds of- [] -> noName- _ -> Right (topDecl, ConstratintAt (fromJust (getLoc ds)))+ DInterfaceConstraint _ ds -> special (ConstratintAt (srcRange ds))+ DImport {} -> noName + DModParam m -> special (ModParamName (srcRange (mpSignature m))+ (mpName m))+ Include {} -> bad "Include"+ DParamDecl {} -> bad "DParamDecl" where noName = Left topDecl- hasName n = Right (topDecl, NamedThing n)+ hasName n = hasName' n []+ hasName' n ms = Right (topDecl, NamedThing n, map NamedThing ms)+ special x = Right (topDecl, x, []) bad x = panic "topDeclName" [x] --- | Returns:--- * The public interface of the imported module--- * Infromation about nested modules in this module--- * New names introduced through this import-doImport :: Located Import -> RenameM (NestedMods, NamingEnv)-doImport li =- do let i = thing li- decls <- lookupImport i- let declsOf = unqualifiedEnv . ifPublic- nested = declsOf <$> ifModules decls- pure (nested, interpImportIface i decls) +{- | Compute the names introduced by a module parameter.+This should be run in a context containing everything that's in scope+except for the module parameters. We don't need to compute a fixed point here+because the signatures (and hence module parameters) cannot contain signatures. ------------------------------------------------------------------------------------ Compute names coming through `open` statements.+The resulting naming environment contains the new names introduced by this+parameter.+-}+doModParam ::+ ModParam PName ->+ RenameM (NamingEnv, RenModParam)+doModParam mp =+ do let sigName = mpSignature mp+ loc = srcRange sigName+ withLoc loc+ do me <- getCurMod -data OpenLoopState = OpenLoopState- { unresolvedOpen :: [ImportG PName]- , scopeImports :: NamingEnv -- names from open/impot- , scopeDefs :: NamingEnv -- names defined in this module- , scopingRel :: NamingEnv -- defs + imports with shadowing- -- (just a cache)- , openLoopChange :: Bool- }+ (sigName',isFake) <-+ case thing sigName of+ ImpTop t -> pure (ImpTop t, False)+ -- XXX: should we record a dependency here?+ -- Not sure what the dependencies are for.. --- | Processing of a single @open@ declaration-processOpen :: NestedMods -> OpenLoopState -> ImportG PName -> OpenLoopState-processOpen modEnvs s o =- case lookupNS NSModule (iModule o) (scopingRel s) of- [] -> s { unresolvedOpen = o : unresolvedOpen s }- [n] ->- case Map.lookup n modEnvs of- Nothing -> panic "openLoop" [ "Missing defintion for module", show n ]- Just def ->- let new = interpImportEnv o def- newImps = new <> scopeImports s- in s { scopeImports = newImps- , scopingRel = scopeDefs s `shadowing` newImps- , openLoopChange = True- }- _ -> s- {- Notes:- * ambiguity will be reported later when we do the renaming- * assumes scoping only grows, which should be true- * we are not adding the names from *either* of the imports- so this may give rise to undefined names, so we may want to- suppress reporing undefined names if there ambiguities for- module names. Alternatively we could add the defitions from- *all* options, but that might lead to spurious ambiguity errors.- -}+ ImpNested n ->+ do mb <- resolveNameMaybe NameUse NSModule n+ (nm,isFake) <- case mb of+ Just rnm -> pure (rnm,False)+ Nothing ->+ do rnm <- reportUnboundName NSModule n+ pure (rnm,True)+ case modPathCommon me (nameModPath nm) of+ Just (_,[],_) ->+ recordError+ (InvalidDependency [ModPath me, NamedThing nm])+ _ -> pure ()+ pure (ImpNested nm, isFake) -{- | Complete the set of import using @open@ declarations.-This should terminate because on each iteration either @unresolvedOpen@-decreases or @openLoopChange@ remians @False@. We don't report errors-here, as they will be reported during renaming anyway. -}-openLoop ::- NestedMods {- ^ Definitions of all known nested modules -} ->- NamingEnv {- ^ Definitions of the module (these shadow) -} ->- [ImportG PName] {- ^ Open declarations -} ->- NamingEnv {- ^ Imported declarations -} ->- NamingEnv {- ^ Completed imports -}-openLoop modEnvs defs os imps =- scopingRel $ loop OpenLoopState- { unresolvedOpen = os- , scopeImports = imps- , scopeDefs = defs- , scopingRel = defs `shadowing` imps- , openLoopChange = True- }- where- loop s- | openLoopChange s =- loop $ foldl' (processOpen modEnvs)- s { unresolvedOpen = [], openLoopChange = False }- (unresolvedOpen s)- | otherwise = s+ unless isFake+ (checkIsModule (srcRange sigName) sigName' ASignature)+ sigEnv <- if isFake then pure mempty else lookupDefines sigName' + {- XXX: It seems a bit odd to use "newModParam" for the names to+ be used for the instantiated type synonyms,+ but what other name could we use? -}+ let newP x = do y <- lift (newModParam me (mpName mp) loc x)+ sets_ (Map.insert y x)+ pure y+ (newEnv',nameMap) <- runStateT Map.empty (travNamingEnv newP sigEnv)+ let paramName = mpAs mp+ let newEnv = case paramName of+ Nothing -> newEnv'+ Just q -> qualify q newEnv'+ pure ( newEnv+ , RenModParam+ { renModParamName = mpName mp+ , renModParamRange = loc+ , renModParamSig = sigName'+ , renModParamInstance = nameMap+ }+ )++{- | Process the parameters of a module.+Should be executed in a context where everything's already in the context,+except the module parameters.+-}+doModParams :: [ModParam PName] -> RenameM (NamingEnv, [RenModParam])+doModParams srcParams =+ do (paramEnvs,params) <- unzip <$> mapM doModParam srcParams++ let repeated = groupBy ((==) `on` renModParamName)+ $ sortBy (compare `on` renModParamName) params++ forM_ repeated \ps ->+ case ps of+ [_] -> pure ()+ ~(p : _) -> recordError (MultipleModParams (renModParamName p)+ (map renModParamRange ps))++ pure (mconcat paramEnvs,params)++++ -------------------------------------------------------------------------------- +rnLocated :: (a -> RenameM b) -> Located a -> RenameM (Located b)+rnLocated f loc = withLoc loc $+ do a' <- f (thing loc)+ return loc { thing = a' } -data WithMods f n = WithMods (NestedMods,ModPath) (f n) -forgetMods :: WithMods f n -> f n-forgetMods (WithMods _ td) = td -renameWithMods ::- Rename (WithMods f) => (NestedMods,ModPath) -> f PName -> RenameM (f Name)-renameWithMods info m = forgetMods <$> rename (WithMods info m) -instance Rename (WithMods TopDecl) where- rename (WithMods info td) = WithMods info <$>++instance Rename TopDecl where+ rename td = case td of- Decl d -> Decl <$> traverse rename d- DPrimType d -> DPrimType <$> traverse rename d- TDNewtype n -> TDNewtype <$> traverse rename n- Include n -> return (Include n)- DParameterFun f -> DParameterFun <$> rename f- DParameterType f -> DParameterType <$> rename f+ Decl d -> Decl <$> traverse rename d+ DPrimType d -> DPrimType <$> traverse rename d+ TDNewtype n -> TDNewtype <$> traverse rename n+ Include n -> return (Include n)+ DModule m -> DModule <$> traverse rename m+ DImport li -> DImport <$> renI li+ DModParam mp -> DModParam <$> rename mp+ DInterfaceConstraint d ds ->+ depsOf (ConstratintAt (srcRange ds))+ (DInterfaceConstraint d <$> rnLocated (mapM rename) ds)+ DParamDecl {} -> panic "rename" ["DParamDecl"] - DParameterConstraint ds ->- case ds of- [] -> pure (DParameterConstraint [])- _ -> depsOf (ConstratintAt (fromJust (getLoc ds)))- $ DParameterConstraint <$> mapM renameLocated ds- DModule m -> DModule <$> traverse (renameWithMods info) m- DImport li -> DImport <$> traverse renI li- where- renI i = do m <- rename (iModule i)- pure i { iModule = m } ++renI :: Located (ImportG (ImpName PName)) ->+ RenameM (Located (ImportG (ImpName Name)))+renI li =+ withLoc (srcRange li)+ do m <- rename (iModule i)+ unless (isFakeName m) (recordImport (srcRange li) m)+ pure li { thing = i { iModule = m } }+ where+ i = thing li+++instance Rename ModParam where+ rename mp =+ do x <- rnLocated rename (mpSignature mp)+ depsOf (ModParamName (srcRange (mpSignature mp)) (mpName mp))+ do ren <- renModParamInstance <$> getModParam (mpName mp)++ {- Here we add 2 "uses" to all type-level names introduced,+ so that we don't get unused warnings for type parameters.+ -}+ mapM_ recordUse [ s | t <- Map.keys ren, nameNamespace t == NSType+ , s <- [t,t] ]++ pure mp { mpSignature = x, mpRenaming = ren }+++renameIfaceModule :: ImpName Name -> Signature PName -> RenameM (Signature Name)+renameIfaceModule nm sig =+ do env <- rmodDefines <$> lookupResolved nm+ let depName = case nm of+ ImpNested n -> NamedThing n+ ImpTop t -> ModPath (TopModule t)+ shadowNames' CheckOverlap env $+ depsOf depName+ do imps <- traverse renI (sigImports sig)+ tps <- traverse rename (sigTypeParams sig)++ ds <- renameSigDecls (sigDecls sig)+ cts <- traverse (rnLocated rename) (sigConstraints sig)+ fun <- traverse rename (sigFunParams sig)++ -- we record a use here to avoid getting a warning in interfaces+ -- that declare only types, and so appear "unused".+ forM_ tps \tp -> recordUse (thing (ptName tp))+ forM_ ds \d -> recordUse $ case d of+ SigTySyn ts _ -> thing (tsName ts)+ SigPropSyn ps _ -> thing (psName ps)++ pure Signature+ { sigImports = imps+ , sigTypeParams = tps+ , sigDecls = ds+ , sigConstraints = cts+ , sigFunParams = fun+ }+ instance Rename ImpName where rename i = case i of ImpTop m -> pure (ImpTop m) ImpNested m -> ImpNested <$> resolveName NameUse NSModule m -instance Rename (WithMods NestedModule) where- rename (WithMods info (NestedModule m)) = WithMods info <$>- do let (nested,mpath) = info- lnm = mName m+instance Rename ModuleInstanceArgs where+ rename args =+ case args of+ DefaultInstArg a -> DefaultInstArg <$> rnLocated rename a+ NamedInstArgs xs -> NamedInstArgs <$> traverse rename xs+ DefaultInstAnonArg {} -> panic "rename" ["DefaultInstAnonArg"]++instance Rename ModuleInstanceNamedArg where+ rename (ModuleInstanceNamedArg x m) =+ ModuleInstanceNamedArg x <$> rnLocated rename m++instance Rename ModuleInstanceArg where+ rename arg =+ case arg of+ ModuleArg m -> ModuleArg <$> rename m+ ParameterArg a -> pure (ParameterArg a)+ AddParams -> pure AddParams++instance Rename NestedModule where+ rename (NestedModule m) =+ do let lnm = mName m nm = thing lnm- newMPath = Nested mpath (getIdent nm) n <- resolveName NameBind NSModule nm depsOf (NamedThing n)- do let env = case Map.lookup n (fst info) of- Just defs -> defs- Nothing -> panic "rename"- [ "Missing environment for nested module", show n ]- -- XXX: we should store in scope somehwere if we want to browse+ do -- XXX: we should store in scope somewhere if we want to browse -- nested modules properly- (_inScope,m1) <- renameModule' nested env newMPath m+ let m' = m { mName = ImpNested <$> mName m }+ (_inScope,m1) <- renameModule' (ImpNested n) m' pure (NestedModule m1 { mName = lnm { thing = n } }) -renameLocated :: Rename f => Located (f PName) -> RenameM (Located (f Name))-renameLocated x =- do y <- rename (thing x)- return x { thing = y }- instance Rename PrimType where rename pt = do x <- rnLocated (renameType NameBind) (primTName pt)@@ -477,7 +836,7 @@ -- Record an additional use for each parameter since we checked -- earlier that all the parameters are used exactly once in the- -- body of the signature. This prevents incorret warnings+ -- body of the signature. This prevents incorrect warnings -- about unused names. mapM_ (recordUse . tpName) (fst cts) @@ -495,10 +854,11 @@ do sig' <- renameSchema (pfSchema a) return a { pfName = n', pfSchema = snd sig' } -rnLocated :: (a -> RenameM b) -> Located a -> RenameM (Located b)-rnLocated f loc = withLoc loc $- do a' <- f (thing loc)- return loc { thing = a' }+instance Rename SigDecl where+ rename decl =+ case decl of+ SigTySyn ts mb -> SigTySyn <$> rename ts <*> pure mb+ SigPropSyn ps mb -> SigPropSyn <$> rename ps <*> pure mb instance Rename Decl where rename d = case d of@@ -509,7 +869,7 @@ DLocated d' r -> withLoc r $ DLocated <$> rename d' <*> pure r - DFixity{} -> panic "renaem" [ "DFixity" ]+ DFixity{} -> panic "rename" [ "DFixity" ] DSignature {} -> panic "rename" [ "DSignature" ] DPragma {} -> panic "rename" [ "DPragma" ] DPatBind {} -> panic "rename" [ "DPatBind " ]@@ -520,11 +880,16 @@ instance Rename Newtype where rename n = shadowNames (nParams n) $- do name' <- rnLocated (renameType NameBind) (nName n)- depsOf (NamedThing (thing name')) $+ do nameT <- rnLocated (renameType NameBind) (nName n)+ nameC <- renameVar NameBind (nConName n)++ depsOf (NamedThing nameC) (addDep (thing nameT))++ depsOf (NamedThing (thing nameT)) $ do ps' <- traverse rename (nParams n) body' <- traverse (traverse rename) (nBody n)- return Newtype { nName = name'+ return Newtype { nName = nameT+ , nConName = nameC , nParams = ps' , nBody = body' } @@ -539,42 +904,57 @@ NSType -> recordUse _ -> const (pure ()) case lkpIn expected of- Just [n] ->- do case nt of- NameBind -> pure ()- NameUse -> addDep n- use n -- for warning- return (Just n)- Just [] -> panic "Renamer" ["Invalid expression renaming environment"]- Just syms ->- do mapM_ use syms -- mark as used to avoid unused warnings- n <- located qn- record (MultipleSyms n syms)- return (Just (head syms))+ Just xs ->+ case xs of+ One n ->+ do case nt of+ NameBind -> pure ()+ NameUse -> addDep n+ use n -- for warning+ return (Just n)+ Ambig symSet ->+ do let syms = Set.toList symSet+ mapM_ use syms -- mark as used to avoid unused warnings+ n <- located qn+ recordError (MultipleSyms n syms)+ return (Just (head syms)) Nothing -> pure Nothing +reportUnboundName :: Namespace -> PName -> RenameM Name+reportUnboundName expected qn =+ do ro <- RenameM ask+ let lkpIn here = Map.lookup qn (namespaceMap here (roNames ro))+ others = [ ns | ns <- allNamespaces+ , ns /= expected+ , Just _ <- [lkpIn ns] ]+ nm <- located qn+ case others of+ -- name exists in a different namespace+ actual : _ -> recordError (WrongNamespace expected actual nm)++ -- the value is just missing+ [] -> recordError (UnboundName expected nm)++ mkFakeName expected qn++isFakeName :: ImpName Name -> Bool+isFakeName m =+ case m of+ ImpTop x -> x == undefinedModName+ ImpNested x ->+ case nameTopModuleMaybe x of+ Just y -> y == undefinedModName+ Nothing -> False++ -- | Resolve a name, and report error on failure resolveName :: NameType -> Namespace -> PName -> RenameM Name resolveName nt expected qn = do mb <- resolveNameMaybe nt expected qn case mb of Just n -> pure n- Nothing ->- do ro <- RenameM ask- let lkpIn here = Map.lookup qn (namespaceMap here (roNames ro))- others = [ ns | ns <- allNamespaces- , ns /= expected- , Just _ <- [lkpIn ns] ]- nm <- located qn- case others of- -- name exists in a different namespace- actual : _ -> record (WrongNamespace expected actual nm)-- -- the value is just missing- [] -> record (UnboundName expected nm)-- mkFakeName expected qn+ Nothing -> reportUnboundName expected qn renameVar :: NameType -> PName -> RenameM Name@@ -590,7 +970,8 @@ mkFakeName :: Namespace -> PName -> RenameM Name mkFakeName ns pn = do ro <- RenameM ask- liftSupply (mkParameter ns (getIdent pn) (roLoc ro))+ liftSupply (mkDeclared ns (TopModule undefinedModName)+ SystemName (getIdent pn) Nothing (roLoc ro)) -- | Rename a schema, assuming that none of its type variables are already in -- scope.@@ -639,7 +1020,7 @@ TTuple fs -> TTuple <$> traverse rename fs TWild -> return TWild TLocated t' r -> withLoc r (TLocated <$> rename t' <*> pure r)- TParens t' -> TParens <$> rename t'+ TParens t' k -> (`TParens` k) <$> rename t' TInfix a o _ b -> do o' <- renameTypeOp o a' <- rename a b' <- rename b@@ -653,7 +1034,7 @@ FCLeft -> return (TInfix t o2 f2 z) FCRight -> do r <- mkTInfix y op z return (TInfix x o1 f1 r)- FCError -> do record (FixityError o1 f1 o2 f2)+ FCError -> do recordError (FixityError o1 f1 o2 f2) return (TInfix t o2 f2 z) mkTInfix (TLocated t' _) op z =@@ -683,8 +1064,14 @@ instance Rename BindDef where rename DPrim = return DPrim+ rename DForeign = return DForeign rename (DExpr e) = DExpr <$> rename e+ rename (DPropGuards cases) = DPropGuards <$> traverse rename cases +instance Rename PropGuardCase where+ rename g = PropGuardCase <$> traverse (rnLocated rename) (pgcProps g)+ <*> rename (pgcExpr g)+ -- NOTE: this only renames types within the pattern. instance Rename Pattern where rename p = case p of@@ -712,7 +1099,8 @@ case more of [] -> case h of UpdSet -> UpdField UpdSet [l] <$> rename e- UpdFun -> UpdField UpdFun [l] <$> rename (EFun emptyFunDesc [PVar p] e)+ UpdFun -> UpdField UpdFun [l] <$>+ rename (EFun emptyFunDesc [PVar p] e) where p = UnQual . selName <$> last ls _ -> UpdField UpdFun [l] <$> rename (EUpd Nothing [ UpdField h more e])@@ -728,9 +1116,6 @@ rename expr = case expr of EVar n -> EVar <$> renameVar NameUse n ELit l -> return (ELit l)- ENeg e -> ENeg <$> rename e- EComplement e -> EComplement- <$> rename e EGenerate e -> EGenerate <$> rename e ETuple es -> ETuple <$> traverse rename es@@ -786,6 +1171,7 @@ x' <- rename x z' <- rename z mkEInfix x' op z'+ EPrefix op e -> EPrefix op <$> rename e checkLabels :: [UpdField PName] -> RenameM ()@@ -795,7 +1181,7 @@ check done l = do case find (overlap l) done of- Just l' -> record (OverlappingRecordUpdate (reLoc l) (reLoc l'))+ Just l' -> recordError (OverlappingRecordUpdate (reLoc l) (reLoc l')) Nothing -> pure () pure (l : done) @@ -827,9 +1213,25 @@ FCRight -> do r <- mkEInfix y op z return (EInfix x o1 f1 r) - FCError -> do record (FixityError o1 f1 o2 f2)+ FCError -> do recordError (FixityError o1 f1 o2 f2) return (EInfix e o2 f2 z) +mkEInfix e@(EPrefix o1 x) op@(o2, f2) y =+ case compareFixity (prefixFixity o1) f2 of+ FCRight -> do+ let warning = PrefixAssocChanged o1 x o2 f2 y+ RenameM $ sets_ (\rw -> rw {rwWarnings = warning : rwWarnings rw})+ r <- mkEInfix x op y+ return (EPrefix o1 r)++ -- Even if the fixities conflict, we make the prefix operator take+ -- precedence.+ _ -> return (EInfix e o2 f2 y)++-- Note that for prefix operator on RHS of infix operator we make the prefix+-- operator always have precedence, so we allow a * -b instead of requiring+-- a * (-b).+ mkEInfix (ELocated e' _) op z = mkEInfix e' op z @@ -921,9 +1323,9 @@ patternEnv = go where go (PVar Located { .. }) =- do n <- liftSupply (mkParameter NSValue (getIdent thing) srcRange)+ do n <- liftSupply (mkLocal NSValue (getIdent thing) srcRange) -- XXX: for deps, we should record a use- return (singletonE thing n)+ return (singletonNS NSValue thing n) go PWild = return mempty go (PTuple ps) = bindVars ps@@ -961,23 +1363,23 @@ -- of the type of the pattern. | null ps -> do loc <- curLoc- n <- liftSupply (mkParameter NSType (getIdent pn) loc)- return (singletonT pn n)+ n <- liftSupply (mkLocal NSType (getIdent pn) loc)+ return (singletonNS NSType pn n) -- This references a type synonym that's not in scope. Record an -- error and continue with a made up name. | otherwise -> do loc <- curLoc- record (UnboundName NSType (Located loc pn))- n <- liftSupply (mkParameter NSType (getIdent pn) loc)- return (singletonT pn n)+ recordError (UnboundName NSType (Located loc pn))+ n <- liftSupply (mkLocal NSType (getIdent pn) loc)+ return (singletonNS NSType pn n) typeEnv (TRecord fs) = bindTypes (map snd (recordElements fs)) typeEnv (TTyApp fs) = bindTypes (map value fs) typeEnv (TTuple ts) = bindTypes ts typeEnv TWild = return mempty typeEnv (TLocated ty loc) = withLoc loc (typeEnv ty)- typeEnv (TParens ty) = typeEnv ty+ typeEnv (TParens ty _) = typeEnv ty typeEnv (TInfix a _ _ b) = bindTypes [a,b] bindTypes [] = return mempty@@ -1005,3 +1407,20 @@ shadowNames ps do n' <- rnLocated (renameType NameBind) n PropSyn n' <$> pure f <*> traverse rename ps <*> traverse rename cs++--------------------------------------------------------------------------------++instance PP RenamedModule where+ ppPrec _ rn = updPPCfg (\cfg -> cfg { ppcfgShowNameUniques = True }) doc+ where+ doc =+ vcat [ "// --- Defines -----------------------------"+ , pp (rmDefines rn)+ , "// --- In scope ----------------------------"+ , pp (rmInScope rn)+ , "// -- Module -------------------------------"+ , pp (rmModule rn)+ , "// -----------------------------------------"+ ]++
src/Cryptol/ModuleSystem/Renamer/Error.hs view
@@ -10,11 +10,14 @@ {-# Language OverloadedStrings #-} module Cryptol.ModuleSystem.Renamer.Error where +import Data.List(intersperse)+ import Cryptol.ModuleSystem.Name import Cryptol.Parser.AST import Cryptol.Parser.Position import Cryptol.Parser.Selector(ppNestedSels) import Cryptol.Utils.PP+import Cryptol.Utils.Ident(modPathSplit) import GHC.Generics (Generic) import Control.DeepSeq@@ -41,35 +44,65 @@ | FixityError (Located Name) Fixity (Located Name) Fixity -- ^ When the fixity of two operators conflict - | InvalidConstraint (Type PName)- -- ^ When it's not possible to produce a Prop from a Type.-- | MalformedBuiltin (Type PName) PName- -- ^ When a builtin type/type-function is used incorrectly.-- | BoundReservedType PName (Maybe Range) Doc- -- ^ When a builtin type is named in a binder.- | OverlappingRecordUpdate (Located [Selector]) (Located [Selector]) -- ^ When record updates overlap (e.g., @{ r | x = e1, x.y = e2 }@) | InvalidDependency [DepName]- deriving (Show, Generic, NFData)+ -- ^ Things that can't depend on each other + | MultipleModParams Ident [Range]+ -- ^ Module parameters with the same name --- We use this because parameter constrstaints have no names+ | InvalidFunctorImport (ImpName Name)+ -- ^ Can't import functors directly++ | UnexpectedNest Range PName+ -- ^ Nested modules were not supposed to appear here++ | ModuleKindMismatch Range (ImpName Name) ModKind ModKind+ -- ^ Exepcted one kind (first one) but found the other (second one)++ deriving (Show, Generic, NFData, Eq, Ord)+++{- | We use this to name dependencies.+In addition to normal names we have a way to refer to module parameters+and top-level module constraints, which have no explicit names -} data DepName = NamedThing Name- | ConstratintAt Range -- ^ identifed by location in source+ -- ^ Something with a name++ | ModPath ModPath+ -- ^ The module at this path++ | ModParamName Range Ident+ {- ^ Note that the range is important not just for error+ reporting but to distinguish module parameters with+ the same name (e.g., in nested functors) -}+ | ConstratintAt Range+ -- ^ Identifed by location in source deriving (Eq,Ord,Show,Generic,NFData) -depNameLoc :: DepName -> Range+depNameLoc :: DepName -> Maybe Range depNameLoc x = case x of- NamedThing n -> nameLoc n- ConstratintAt r -> r- + NamedThing n -> Just (nameLoc n)+ ConstratintAt r -> Just r+ ModParamName r _ -> Just r+ ModPath {} -> Nothing +data ModKind = AFunctor | ASignature | AModule+ deriving (Show, Generic, NFData, Eq, Ord)++instance PP ModKind where+ ppPrec _ e =+ case e of+ AFunctor -> "a functor"+ ASignature -> "an interface"+ AModule -> "a module"+++ instance PP RenamerError where ppPrec _ e = case e of @@ -119,19 +152,6 @@ , text "are not compatible." , text "You may use explicit parentheses to disambiguate." ]) - InvalidConstraint ty ->- hang (hsep $ [text "[error]"] ++ maybe [] (\r -> [text "at" <+> pp r]) (getLoc ty))- 4 (fsep [ pp ty, text "is not a valid constraint" ])-- MalformedBuiltin ty pn ->- hang (hsep $ [text "[error]"] ++ maybe [] (\r -> [text "at" <+> pp r]) (getLoc ty))- 4 (fsep [ text "invalid use of built-in type", pp pn- , text "in type", pp ty ])-- BoundReservedType n loc src ->- hang (hsep $ [text "[error]"] ++ maybe [] (\r -> [text "at" <+> pp r]) loc)- 4 (fsep [ text "built-in type", quotes (pp n), text "shadowed in", src ])- OverlappingRecordUpdate xs ys -> hang "[error] Overlapping record updates:" 4 (vcat [ ppLab xs, ppLab ys ])@@ -140,10 +160,32 @@ InvalidDependency ds -> hang "[error] Invalid recursive dependency:"- 4 (vcat [ "•" <+> pp x <.> ", defined at" <+> ppR (depNameLoc x)+ 4 (vcat [ "•" <+> pp x <.>+ case depNameLoc x of+ Just r -> ", defined at" <+> ppR r+ Nothing -> mempty | x <- ds ]) where ppR r = pp (from r) <.> "--" <.> pp (to r) + MultipleModParams x rs ->+ hang ("[error] Multiple parameters with name" <+> backticks (pp x))+ 4 (vcat [ "•" <+> pp r | r <- rs ])++ InvalidFunctorImport x ->+ hang ("[error] Invalid import of functor" <+> backticks (pp x))+ 4 "• Functors need to be instantiated before they can be imported."++ UnexpectedNest s x ->+ hang ("[error] at" <+> pp s)+ 4 ("submodule" <+> backticks (pp x) <+> "may not be defined here.")++ ModuleKindMismatch r x expected actual ->+ hang ("[error] at" <+> pp r)+ 4 (vcat [ "• Expected" <+> pp expected+ , "•" <+> backticks (pp x) <+> "is" <+> pp actual+ ])++ instance PP DepName where ppPrec _ d = case d of@@ -153,6 +195,11 @@ NSModule -> "submodule" <+> pp n NSType -> "type" <+> pp n NSValue -> pp n+ ModParamName _r i -> "module parameter" <+> pp i+ ModPath mp ->+ case modPathSplit mp of+ (m,[]) -> "module" <+> pp m+ (_,is) -> "submodule" <+> hcat (intersperse "::" (map pp is)) @@ -161,27 +208,29 @@ data RenamerWarning = SymbolShadowed PName Name [Name] | UnusedName Name+ | PrefixAssocChanged PrefixOp (Expr Name) (Located Name) Fixity (Expr Name) deriving (Show, Generic, NFData) instance Eq RenamerWarning where x == y = compare x y == EQ --- used to determine in what order ot show things+-- used to determine in what order to show things instance Ord RenamerWarning where compare w1 w2 =- case w1 of- SymbolShadowed x y _ ->- case w2 of- SymbolShadowed x' y' _ -> compare (byStart y,x) (byStart y',x')- _ -> LT- UnusedName x ->- case w2 of- UnusedName y -> compare (byStart x) (byStart y)- _ -> GT+ case (w1, w2) of+ (SymbolShadowed x y _, SymbolShadowed x' y' _) ->+ compare (byStart y, x) (byStart y', x')+ (UnusedName x, UnusedName x') ->+ compare (byStart x) (byStart x')+ (PrefixAssocChanged _ _ op _ _, PrefixAssocChanged _ _ op' _ _) ->+ compare (from $ srcRange op) (from $ srcRange op')+ _ -> compare (priority w1) (priority w2) where byStart = from . nameLoc-+ priority SymbolShadowed {} = 0 :: Int+ priority UnusedName {} = 1+ priority PrefixAssocChanged {} = 2 instance PP RenamerWarning where ppPrec _ (SymbolShadowed k x os) =@@ -201,5 +250,12 @@ hang (text "[warning] at" <+> pp (nameLoc x)) 4 (text "Unused name:" <+> pp x) -+ ppPrec _ (PrefixAssocChanged prefixOp x infixOp infixFixity y) =+ hang (text "[warning] at" <+> pp (srcRange infixOp))+ 4 $ fsep [ backticks (pp old)+ , "is now parsed as"+ , backticks (pp new) ] + where+ old = EInfix (EPrefix prefixOp x) infixOp infixFixity y+ new = EPrefix prefixOp (EInfix x infixOp infixFixity y)
+ src/Cryptol/ModuleSystem/Renamer/ImplicitImports.hs view
@@ -0,0 +1,114 @@+{- |+We add implicit imports are for public nested modules. This allows+using definitions from nested modules without having to explicitly import+them, for example:++module A where++ submodule B where+ x = 0x20++ y = x // This works because of the implicit import of `B`++Restriction:+============++We only add impicit imports of modules that are syntactically visiable+in the source code. Consider the following example:++module A where+ submodule M = F {X} -- F,X are external modules (e.g., top-level)++We will add an implicit import for `M`, but *NO* implicit imports for+any modules imported vial `M` as those are not sytnactically visible+in the source (i.e., we have to know what `F` refers to).++This restriction allows us to add implicit imports before doing the+`Imports` pass.+-}++module Cryptol.ModuleSystem.Renamer.ImplicitImports+ ( addImplicitNestedImports+ ) where++import Data.List(partition)++import Cryptol.Parser.Position(Range)+import Cryptol.Utils.Ident(packModName)+import Cryptol.Parser.AST++{- | Add additional imports for modules nested withing this one -}+addImplicitNestedImports :: [TopDecl PName] -> [TopDecl PName]+addImplicitNestedImports = snd . addImplicitNestedImports'++{- | Returns:++ * declarations with additional imports and+ * the public module names of this module and its children.+-}+addImplicitNestedImports' ::+ [TopDecl PName] -> ([[Ident]], [TopDecl PName])+addImplicitNestedImports' decls =+ (concat exportedMods, concat newDecls ++ other)+ where+ (mods,other) = partition isNestedMod decls+ (newDecls,exportedMods) = unzip (map processModule mods)+++processModule :: TopDecl PName -> ([TopDecl PName], [[Ident]])+processModule ~dcl@(DModule m) =+ let NestedModule m1 = tlValue m+ in+ case mDef m1 of+ NormalModule ds ->+ let (childExs, ds1) = addImplicitNestedImports' ds+ mname = getIdent (thing (mName m1))+ imps = map (mname :) ([] : childExs) -- this & nested+ loc = srcRange (mName m1)+ in ( DModule m { tlValue = NestedModule m1 { mDef = NormalModule ds1 } }+ : map (mkImp loc) imps+ , case tlExport m of+ Public -> imps+ Private -> []+ )++ FunctorInstance {} -> ([dcl], [])+ InterfaceModule {} -> ([dcl], [])+++++isNestedMod :: TopDecl name -> Bool+isNestedMod d =+ case d of+ DModule tl -> case tlValue tl of+ NestedModule m -> not (mIsFunctor m)+ _ -> False++-- | Make a name qualifier out of a list of identifiers.+isToQual :: [Ident] -> ModName+isToQual is = packModName (map identText is)++-- | Make a module name out of a list of identifier.+-- This is the name of the module we are implicitly importing.+isToName :: [Ident] -> PName+isToName is = case is of+ [i] -> mkUnqual i+ _ -> mkQual (isToQual (init is)) (last is)++-- | Make an implicit import declaration.+mkImp :: Range -> [Ident] -> TopDecl PName+mkImp loc xs =+ DImport+ Located+ { srcRange = loc+ , thing = Import+ { iModule = ImpNested (isToName xs)+ , iAs = Just (isToQual xs)+ , iSpec = Nothing+ , iInst = Nothing+ }+ }+++
+ src/Cryptol/ModuleSystem/Renamer/Imports.hs view
@@ -0,0 +1,576 @@+{- |++This module deals with imports of nested modules (@import submodule@).+This is more complex than it might seem at first because to resolve a+declaration like @import submodule X@ we need to resolve what @X@+referes to before we know what it will import.++Even triciker is the case for functor instantiations:++ module M = F { X }+ import M++In this case, even if we know what `M` referes to, we first need to+resolve `F`, so that we can generate the instantiation and generate+fresh names for names defined by `M`.++If we want to support applicative semantics, then before instantiation+`M` we also need to resolve `X` so that we know if this instantiation has+already been generated.++An overall guiding principle of the design is that we assume that declarations+can be ordered in dependency order, and submodules can be processed one+at a time. In particular, this does not allow recursion across modules,+or functor instantiations depending on their arguments.++Thus, the following is OK:++module A where+ x = 0x2++ submodule B where+ y = x++ z = B::y+++However, this is not OK:++ submodule A = F X+ submodule F where+ import A+-}++{-# Language BlockArguments #-}+{-# Language TypeSynonymInstances, FlexibleInstances #-}+module Cryptol.ModuleSystem.Renamer.Imports+ ( resolveImports+ , ResolvedModule(..)+ , ModKind(..)+ , ResolvedLocal+ , ResolvedExt+ )+ where++import Data.Maybe(fromMaybe)+import Data.Set(Set)+import qualified Data.Set as Set+import Data.Map (Map)+import qualified Data.Map as Map+import Data.List(foldl')+import Control.Monad(when)+import qualified MonadLib as M++import Cryptol.Utils.PP(pp)+import Cryptol.Utils.Panic(panic)+import Cryptol.Utils.Ident(ModName,ModPath(..),Namespace(..),OrigName(..))++import Cryptol.Parser.AST+ ( ImportG(..),PName, ModuleInstanceArgs(..), ImpName(..) )+import Cryptol.ModuleSystem.Binds (Mod(..), TopDef(..), modNested, ModKind(..))+import Cryptol.ModuleSystem.Name+ ( Name, Supply, SupplyT, runSupplyT, liftSupply, freshNameFor+ , asOrigName, nameIdent, nameTopModule )+import Cryptol.ModuleSystem.Names(Names(..))+import Cryptol.ModuleSystem.NamingEnv+ ( NamingEnv(..), lookupNS, shadowing, travNamingEnv+ , interpImportEnv, zipByTextName, filterUNames )+++{- | This represents a resolved module or signaure.+The type parameter helps us distinguish between two types of resolved modules:++ 1. Resolved modules that are *inputs* to the algorithm (i.e., they are+ defined outside the current module). For such modules the type+ parameter is @imps@ is ()++ 2. Resolved modules that are *outputs* of the algorithm (i.e., they+ are defined within the current module). For such modules the type+ parameter @imps@ contains the naming environment for things+ that came in through the import.++Note that signaures are never "imported", however we do need to keep them+here so that signatures in a functor are properly instantiated when+the functor is instantiated.+-}+data ResolvedModule imps = ResolvedModule+ { rmodDefines :: NamingEnv -- ^ Things defined by the module/signature.+ , rmodPublic :: !(Set Name) -- ^ Exported names+ , rmodKind :: ModKind -- ^ What sort of thing are we+ , rmodNested :: Set Name -- ^ Modules and signatures nested in this one+ , rmodImports :: imps+ {- ^ Resolved imports. External modules need not specify this field,+ it is just part of the thing we compute for local modules. -}+ }+++-- | A resolved module that's defined in (or is) the current top-level module+type ResolvedLocal = ResolvedModule NamingEnv++-- | A resolved module that's not defined in the current top-level module+type ResolvedExt = ResolvedModule ()+++resolveImports ::+ (ImpName Name -> Mod ()) ->+ TopDef ->+ Supply ->+ (Map (ImpName Name) ResolvedLocal, Supply)+resolveImports ext def su =+ case def of++ TopMod m mo ->+ do let cur = todoModule mo+ newS = doModuleStep CurState+ { curMod = cur+ , curTop = m+ , externalModules = ext+ , doneModules = mempty+ , nameSupply = su+ , changes = False+ }+++ case tryFinishCurMod cur newS of+ Just r -> add m r newS+ Nothing -> add m r s1+ where (r,s1) = forceFinish newS++ TopInst m f as ->+ do let s = CurState+ { curMod = ()+ , curTop = m+ , externalModules = ext+ , doneModules = mempty+ , nameSupply = su+ , changes = False+ }++ case tryInstanceMaybe s (ImpTop m) (f,as) of+ Just (r,newS) -> add m r newS+ Nothing -> (Map.singleton (ImpTop m) forceResolveInst, su)++ where+ toNest m = Map.fromList [ (ImpNested k, v) | (k,v) <- Map.toList m ]+ add m r s = ( Map.insert (ImpTop m) r (toNest (doneModules s))+ , nameSupply s+ )+++++--------------------------------------------------------------------------------+++-- | This keeps track of the current state of resolution of a module.+type Todo = Mod ModState++data ModState = ModState+ { modOuter :: NamingEnv+ -- ^ Things which come in scope from outer modules++ , modImported :: NamingEnv+ -- ^ Things which come in scope via imports. These shadow outer names.+ }+++-- | Initial state of a module that needs processing.+todoModule :: Mod () -> Todo+todoModule = fmap (const emptyModState)+ where+ emptyModState =+ ModState+ { modOuter = mempty+ , modImported = mempty+ }++{- | A module is fully processed when we are done with all its:++ * submodule imports+ * instantiations+ * nested things (signatures and modules)+-}+isDone :: Todo -> Bool+isDone m = null (modImports m) &&+ Map.null (modInstances m) &&+ Map.null (modMods m)+++-- | Finish up all unfinished modules as best as we can+forceFinish :: CurState -> (ResolvedLocal,CurState)+forceFinish s0 =+ let this = curMod s0+ add k v s = s { doneModules = Map.insert k v (doneModules s) }+ s1 = foldl' (\s k -> add k forceResolveInst s) s0+ (Map.keys (modInstances this))++ doNestMod s (k,m) =+ let (r,s') = forceFinish s { curMod = m }+ in add k r s'++ in ( forceResolveMod this+ , foldl' doNestMod s1 (Map.toList (modMods this))+ )+++-- | A place-holder entry for instnatitations we couldn't resolve.+forceResolveInst :: ResolvedLocal+forceResolveInst =+ ResolvedModule+ { rmodDefines = mempty+ , rmodPublic = mempty+ , rmodKind = AModule+ , rmodNested = Set.empty+ , rmodImports = mempty+ }++-- | Finish up unresolved modules as well as we can, in situations where+-- the program contains an error.+forceResolveMod :: Todo -> ResolvedLocal+forceResolveMod todo =+ ResolvedModule+ { rmodDefines = modDefines todo+ , rmodPublic = modPublic todo+ , rmodKind = modKind todo+ , rmodNested = Map.keysSet (modMods todo)+ , rmodImports = modImported (modState todo)+ }++++++pushImport :: ImportG (ImpName PName) -> Todo -> Todo+pushImport i m = m { modImports = i : modImports m }++pushInst :: Name -> (ImpName PName, ModuleInstanceArgs PName) -> Todo -> Todo+pushInst k v m = m { modInstances = Map.insert k v (modInstances m) }++pushMod :: Name -> Todo -> Todo -> Todo+pushMod k v m = m { modMods = Map.insert k v (modMods m) }++updMS :: (ModState -> ModState) -> Todo -> Todo+updMS f m = m { modState = f (modState m) }+--------------------------------------------------------------------------------++++externalMod :: Mod () -> ResolvedExt+externalMod m = ResolvedModule+ { rmodDefines = modDefines m+ , rmodPublic = modPublic m+ , rmodKind = modKind m+ , rmodNested = modNested m+ , rmodImports = ()+ }++{- | This is used when we need to use a local resolved module as an input+ to another module. -}+forget :: ResolvedLocal -> ResolvedExt+forget r = r { rmodImports = () }++type CurState = CurState' Todo++data CurState' a = CurState+ { curMod :: a+ -- ^ This is what needs to be done++ , curTop :: !ModName+ {- ^ The top-level module we are working on. This does not change+ throught the algorithm, it is just convenient to pass it here with + all the other stuff. -}++ , externalModules :: ImpName Name -> Mod ()+ -- ^ Modules defined outside the current top-level modules++ , doneModules :: Map Name ResolvedLocal+ {- ^ Nested modules/signatures in the current top-level modules.+ These may be either defined locally, or be the result of+ instantiating a functor. Note that the functor itself may be+ either local or external.+ -}++ , nameSupply :: Supply+ -- ^ Use this to instantiate functors++ , changes :: Bool+ -- ^ True if something changed on the last iteration+ }++updCur :: CurState -> (Todo -> Todo) -> CurState+updCur m f = m { curMod = f (curMod m) }++updCurMS :: CurState -> (ModState -> ModState) -> CurState+updCurMS s f = updCur s (updMS f)++class HasCurScope a where+ curScope :: CurState' a -> NamingEnv++instance HasCurScope () where+ curScope _ = mempty++instance HasCurScope Todo where+ curScope s = modDefines m `shadowing` modImported ms `shadowing` modOuter ms+ where+ m = curMod s+ ms = modState m+++-- | Keep applying a transformation while things are changing+doStep :: (CurState -> CurState) -> (CurState -> CurState)+doStep f s0 = go (changes s0) s0+ where+ go ch s = let s1 = f s { changes = False }+ in if changes s1+ then go True s1+ else s { changes = ch }++-- | Is this a known name for a module in the current scope?+knownPName :: HasCurScope a => CurState' a -> PName -> Maybe Name+knownPName s x =+ do ns <- lookupNS NSModule x (curScope s)+ case ns of+ One n -> pure n+ {- NOTE: since we build up what's in scope incrementally,+ it is possible that this would eventually be ambiguous,+ which we'll detect during actual renaming. -}++ Ambig {} -> Nothing+ {- We treat ambiguous imports as undefined, which may lead to+ spurious "undefined X" errors. To avoid this we should prioritize+ reporting "ambiguous X" errors. -}++-- | Is the module mentioned in this import known in the current scope?+knownImpName ::+ HasCurScope a => CurState' a -> ImpName PName -> Maybe (ImpName Name)+knownImpName s i =+ case i of+ ImpTop m -> pure (ImpTop m)+ ImpNested m -> ImpNested <$> knownPName s m++-- | Is the module mentioned in the import already resolved?+knownModule ::+ HasCurScope a => CurState' a -> ImpName Name -> Maybe ResolvedExt+knownModule s x+ | root == curTop s =+ case x of+ ImpNested y -> forget <$> Map.lookup y (doneModules s)+ ImpTop {} -> Nothing -- or panic? recursive import++ | otherwise = Just (externalMod (externalModules s x))++ where+ root = case x of+ ImpTop r -> r+ ImpNested n -> nameTopModule n++--------------------------------------------------------------------------------+++{- | Try to resolve an import. If the imported module can be resolved,+and it refers to a module that's already been resolved, then we do the+import and extend the current scoping environment. Otherwise, we just+queue the import back on the @modImports@ of the current module to be tried+again later.-}+tryImport :: CurState -> ImportG (ImpName PName) -> CurState+tryImport s imp =+ fromMaybe (updCur s (pushImport imp)) -- not ready, put it back on the q+ do let srcName = iModule imp+ mname <- knownImpName s srcName+ ext <- knownModule s mname++ let isPub x = x `Set.member` rmodPublic ext+ new = case rmodKind ext of+ AModule -> interpImportEnv imp+ (filterUNames isPub (rmodDefines ext))+ AFunctor -> mempty+ ASignature -> mempty++ pure $ updCurMS s { changes = True }+ \ms -> ms { modImported = new <> modImported ms }++-- | Resolve all imports in the current modules+doImportStep :: CurState -> CurState+doImportStep s = foldl' tryImport s1 (modImports (curMod s))+ where+ s1 = updCur s \m -> m { modImports = [] }+++{- | Try to instantiate a functor. This succeeds if we can resolve the functor+and the arguments and the both refer to already resolved names.+Note: at the moment we ignore the arguments, but we'd have to do that in+order to implment applicative behavior with caching. -}+tryInstanceMaybe ::+ HasCurScope a =>+ CurState' a ->+ ImpName Name ->+ (ImpName PName, ModuleInstanceArgs PName)+ {- ^ Functor and arguments -} ->+ Maybe (ResolvedLocal,CurState' a)+tryInstanceMaybe s mn (f,_xs) =+ do fn <- knownImpName s f+ let path = case mn of+ ImpTop m -> TopModule m+ ImpNested m ->+ case asOrigName m of+ Just og -> Nested (ogModule og) (ogName og)+ Nothing ->+ panic "tryInstanceMaybe" [ "Not a top-level name" ]+ doInstantiateByName False path fn s++{- | Try to instantiate a functor. If successful, then the newly instantiated+module (and all things nested in it) are going to be added to the+@doneModules@ field. Otherwise, we queue up the instantiatation in+@curMod@ for later processing -}+tryInstance ::+ CurState ->+ Name ->+ (ImpName PName, ModuleInstanceArgs PName) ->+ CurState+tryInstance s mn (f,xs) =+ case tryInstanceMaybe s (ImpNested mn) (f,xs) of+ Nothing -> updCur s (pushInst mn (f,xs))+ Just (def,s1) -> s1 { changes = True+ , doneModules = Map.insert mn def (doneModules s1)+ }++{- | Generate a fresh instance for the functor with the given name. -}+doInstantiateByName ::+ HasCurScope a =>+ Bool+ {- ^ This indicates if the result is a functor or not. When instantiating+ a functor applied to some arguments the result is not a functor. However,+ if we are instantiating a functor nested within some functor that's being+ instantiated, then the result is still a functor. -} ->+ ModPath {- ^ Path for instantiated names -} ->+ ImpName Name {- ^ Name of the functor/module being instantiated -} ->+ CurState' a -> Maybe (ResolvedLocal,CurState' a)++doInstantiateByName keepArgs mpath fname s =+ do def <- knownModule s fname+ pure (doInstantiate keepArgs mpath def s)++++{- | Generate a new instantiation of the given module/signature.+Note that the module might not be a functor itself (e.g., if we are+instantiating something nested in a functor -}+doInstantiate ::+ HasCurScope a =>+ Bool {- ^ See `doInstantiateByName` -} ->+ ModPath {- ^ Path for instantiated names -} ->+ ResolvedExt {- ^ The thing being instantiated -} ->+ CurState' a -> (ResolvedLocal,CurState' a)+doInstantiate keepArgs mpath def s = (newDef, Set.foldl' doSub newS nestedToDo)+ where+ ((newEnv,newNameSupply),nestedToDo) =+ M.runId+ $ M.runStateT Set.empty+ $ runSupplyT (nameSupply s)+ $ travNamingEnv instName+ $ rmodDefines def++ newS = s { nameSupply = newNameSupply }++ pub = let inst = zipByTextName (rmodDefines def) newEnv+ in Set.fromList [ case Map.lookup og inst of+ Just newN -> newN+ Nothing -> panic "doInstantiate.pub"+ [ "Lost a name", show og ]+ | og <- Set.toList (rmodPublic def)+ ]+++ newDef = ResolvedModule { rmodDefines = newEnv+ , rmodPublic = pub+ , rmodKind = case rmodKind def of+ AFunctor ->+ if keepArgs then AFunctor+ else AModule+ ASignature -> ASignature+ AModule -> AModule++ , rmodNested = Set.map snd nestedToDo+ , rmodImports = mempty+ {- we don't do name resolution on the instantiation+ the usual way: instead the functor and the+ arguments are renamed separately, then we+ we do a pass where we replace:+ defined names of functor by instantiations+ parameter by actual names in arguments.+ -}+ }++ doSub st (oldSubName,newSubName) =+ case doInstantiateByName True (Nested mpath (nameIdent newSubName))+ (ImpNested oldSubName) st of+ Just (idef,st1) -> st1 { doneModules = Map.insert newSubName idef+ (doneModules st1) }+ Nothing -> panic "doInstantiate.doSub"+ [ "Missing nested module:", show (pp oldSubName) ]++ instName :: Name -> SupplyT (M.StateT (Set (Name,Name)) M.Id) Name+ instName x =+ do y <- liftSupply (freshNameFor mpath x)+ when (x `Set.member` rmodNested def)+ (M.lift (M.sets_ (Set.insert (x,y))))+ pure y+++-- | Try to make progress on all instantiations.+doInstancesStep :: CurState -> CurState+doInstancesStep s = Map.foldlWithKey' tryInstance s0 (modInstances (curMod s))+ where+ s0 = updCur s \m' -> m' { modInstances = Map.empty }++tryFinishCurMod :: Todo -> CurState -> Maybe ResolvedLocal+tryFinishCurMod m newS+ | isDone newM =+ Just ResolvedModule+ { rmodDefines = modDefines m+ , rmodPublic = modPublic m+ , rmodKind = modKind m+ , rmodNested = Set.unions+ [ Map.keysSet (modInstances m)+ , Map.keysSet (modMods m)+ ]+ , rmodImports = modImported (modState newM)+ }++ | otherwise = Nothing+ where newM = curMod newS+++-- | Try to resolve the "normal" module with the given name.+tryModule :: CurState -> Name -> Todo -> CurState+tryModule s nm m =+ case tryFinishCurMod m newS of+ Just rMod ->+ newS { curMod = curMod s+ , doneModules = Map.insert nm rMod (doneModules newS)+ , changes = True+ }+ Nothing -> newS { curMod = pushMod nm newM (curMod s) }+ where+ s1 = updCur s \_ -> updMS (\ms -> ms { modOuter = curScope s }) m+ newS = doModuleStep s1+ newM = curMod newS++-- | Process all submodules of a module.+doModulesStep :: CurState -> CurState+doModulesStep s = Map.foldlWithKey' tryModule s0 (modMods m)+ where+ m = curMod s+ s0 = s { curMod = m { modMods = mempty } }++++-- | All steps involved in processing a module.+doModuleStep :: CurState -> CurState+doModuleStep = doStep step+ where+ step = doStep doModulesStep+ . doStep doInstancesStep+ . doStep doImportStep++
src/Cryptol/ModuleSystem/Renamer/Monad.hs view
@@ -9,30 +9,34 @@ {-# Language RecordWildCards #-} {-# Language FlexibleContexts #-} {-# Language BlockArguments #-}+{-# Language OverloadedStrings #-} module Cryptol.ModuleSystem.Renamer.Monad where -import Data.List(sort)+import Data.List(sort,foldl') import Data.Set(Set) import qualified Data.Set as Set-import qualified Data.Foldable as F import Data.Map.Strict ( Map ) import qualified Data.Map.Strict as Map-import qualified Data.Sequence as Seq import qualified Data.Semigroup as S import MonadLib hiding (mapM, mapM_) import Prelude () import Prelude.Compat +import Cryptol.Utils.PP(pp)+import Cryptol.Utils.Panic(panic)+import Cryptol.Utils.Ident(modPathCommon,OrigName(..),OrigSource(..)) import Cryptol.ModuleSystem.Name import Cryptol.ModuleSystem.NamingEnv+import Cryptol.ModuleSystem.Binds import Cryptol.ModuleSystem.Interface import Cryptol.Parser.AST+import Cryptol.TypeCheck.AST(ModParamNames) import Cryptol.Parser.Position-import Cryptol.Utils.Panic (panic)-import Cryptol.Utils.Ident(modPathCommon) import Cryptol.ModuleSystem.Renamer.Error+import Cryptol.ModuleSystem.Renamer.Imports+ (ResolvedLocal,rmodKind,rmodDefines,rmodNested) -- | Indicates if a name is in a binding poisition or a use site data NameType = NameBind | NameUse@@ -42,22 +46,41 @@ { renSupply :: Supply -- ^ Use to make new names , renContext :: ModPath -- ^ We are renaming things in here , renEnv :: NamingEnv -- ^ This is what's in scope- , renIfaces :: ModName -> Iface+ , renIfaces :: Map ModName (Either ModParamNames Iface)+ -- ^ External modules } newtype RenameM a = RenameM { unRenameM :: ReaderT RO (StateT RW Lift) a } data RO = RO- { roLoc :: Range- , roNames :: NamingEnv- , roIfaces :: ModName -> Iface- , roCurMod :: ModPath -- ^ Current module we are working on+ { roLoc :: Range+ , roNames :: NamingEnv+ , roExternal :: Map ModName (Maybe Iface, Map (ImpName Name) (Mod ()))+ -- ^ Externally loaded modules. `Mod` is defined in 'Cryptol.Renamer.Binds'.++ , roCurMod :: ModPath -- ^ Current module we are working on+ , roNestedMods :: Map ModPath Name+ {- ^ Maps module paths to the actual name for it. This is used+ for dependency tracking, to find the name of a containing module.+ See the note on `addDep`. -}++ , roResolvedModules :: Map (ImpName Name) ResolvedLocal+ -- ^ Info about locally defined modules++ , roModParams :: Map Ident RenModParam+ {- ^ Module parameters. These are used when rename the module parameters,+ and only refer to the parameters of the current module (i.e., no+ outer parameters as those are not needed) -}++ , roFromModParam :: Map Name DepName+ -- ^ Keeps track of which names were introduce by module parameters+ -- and which one. The `DepName` is always a `ModParamName`. } data RW = RW { rwWarnings :: ![RenamerWarning]- , rwErrors :: !(Seq.Seq RenamerError)+ , rwErrors :: !(Set RenamerError) , rwSupply :: !Supply , rwNameUseCount :: !(Map Name Int) -- ^ How many times did we refer to each name.@@ -72,11 +95,24 @@ -- see 'depsOf' , rwExternalDeps :: !IfaceDecls- -- ^ Info about imported things+ -- ^ Info about imported things, from external modules } +data RenModParam = RenModParam+ { renModParamName :: Ident+ , renModParamRange :: Range+ , renModParamSig :: ImpName Name+ , renModParamInstance :: Map Name Name+ {- ^ Maps names that come into scope through this parameter+ to the names in the *module interface*.+ This is for functors, NOT functor instantantiations. -}+ }++++ instance S.Semigroup a => S.Semigroup (RenameM a) where {-# INLINE (<>) #-} a <> b =@@ -125,7 +161,7 @@ warns = sort (rwWarnings rw ++ warnUnused (renContext info) (renEnv info) rw) (a,rw) = runM (unRenameM m) ro- RW { rwErrors = Seq.empty+ RW { rwErrors = Set.empty , rwWarnings = [] , rwSupply = renSupply info , rwNameUseCount = Map.empty@@ -136,15 +172,24 @@ ro = RO { roLoc = emptyRange , roNames = renEnv info- , roIfaces = renIfaces info+ , roExternal = Map.mapWithKey toModMap (renIfaces info) , roCurMod = renContext info , roNestedMods = Map.empty+ , roResolvedModules = mempty+ , roModParams = mempty+ , roFromModParam = mempty } - res | Seq.null (rwErrors rw) = Right (a,rwSupply rw)- | otherwise = Left (F.toList (rwErrors rw))+ res | Set.null (rwErrors rw) = Right (a,rwSupply rw)+ | otherwise = Left (Set.toList (rwErrors rw)) + toModMap t ent =+ case ent of+ Left ps -> (Nothing, Map.singleton (ImpTop t) (ifaceSigToMod ps))+ Right i -> (Just i, modToMap (ImpTop t) (ifaceToMod i) mempty) ++ setCurMod :: ModPath -> RenameM a -> RenameM a setCurMod mpath (RenameM m) = RenameM $ mapReader (\ro -> ro { roCurMod = mpath }) m@@ -155,7 +200,57 @@ getNamingEnv :: RenameM NamingEnv getNamingEnv = RenameM (asks roNames) +setResolvedLocals :: Map (ImpName Name) ResolvedLocal -> RenameM a -> RenameM a+setResolvedLocals mp (RenameM m) =+ RenameM $ mapReader (\ro -> ro { roResolvedModules = mp }) m +lookupResolved :: ImpName Name -> RenameM ResolvedLocal+lookupResolved nm =+ do mp <- RenameM (roResolvedModules <$> ask)+ pure case Map.lookup nm mp of+ Just r -> r++ -- XXX: could this happen because we couldn't resolve a module?+ Nothing -> panic "lookupResolved"+ [ "Missing module: " ++ show nm ]++setModParams :: [RenModParam] -> RenameM a -> RenameM a+setModParams ps (RenameM m) =+ do let pmap = Map.fromList [ (renModParamName p, p) | p <- ps ]++ newFrom =+ foldLoop ps mempty \p mp ->+ let nm = ModParamName (renModParamRange p) (renModParamName p)+ in foldLoop (Map.keys (renModParamInstance p)) mp \x ->+ Map.insert x nm++ upd ro = ro { roModParams = pmap+ , roFromModParam = newFrom <> roFromModParam ro+ }++ RenameM (mapReader upd m)+++foldLoop :: [a] -> b -> (a -> b -> b) -> b+foldLoop xs b f = foldl' (flip f) b xs++getModParam :: Ident -> RenameM RenModParam+getModParam p =+ do ps <- RenameM (roModParams <$> ask)+ case Map.lookup p ps of+ Just r -> pure r+ Nothing -> panic "getModParam" [ "Missing module paramter", show p ]++getNamesFromModParams :: RenameM (Map Name DepName)+getNamesFromModParams = RenameM (roFromModParam <$> ask)++getLocalModParamDeps :: RenameM (Map Ident DepName)+getLocalModParamDeps =+ do ps <- RenameM (roModParams <$> ask)+ let toName mp = ModParamName (renModParamRange mp) (renModParamName mp)+ pure (toName <$> ps)++ setNestedModule :: Map ModPath Name -> RenameM a -> RenameM a setNestedModule mp (RenameM m) = RenameM $ mapReader (\ro -> ro { roNestedMods = mp }) m@@ -164,12 +259,16 @@ nestedModuleOrig x = RenameM (asks (Map.lookup x . roNestedMods)) --- | Record an error. XXX: use a better name-record :: RenamerError -> RenameM ()-record f = RenameM $+-- | Record an error.+recordError :: RenamerError -> RenameM ()+recordError f = RenameM $ do RW { .. } <- get- set RW { rwErrors = rwErrors Seq.|> f, .. }+ set RW { rwErrors = Set.insert f rwErrors, .. } +recordWarning :: RenamerWarning -> RenameM ()+recordWarning w =+ RenameM $ sets_ \rw -> rw { rwWarnings = w : rwWarnings rw }+ collectIfaceDeps :: RenameM a -> RenameM (IfaceDecls,a) collectIfaceDeps (RenameM m) = RenameM@@ -191,7 +290,7 @@ pure a -- | This is used when renaming a group of things. The result contains--- dependencies between names defines and the group, and is intended to+-- dependencies between names defined in the group, and is intended to -- be used to order the group members in dependency order. depGroup :: RenameM a -> RenameM (a, Map DepName (Set Name)) depGroup (RenameM m) = RenameM@@ -230,58 +329,39 @@ | CheckNone -- ^ Don't check the environment deriving (Eq,Show) +-- | Report errors if the given naming environemnt contains multiple+-- definitions for the same symbol+checkOverlap :: NamingEnv -> RenameM NamingEnv+checkOverlap env =+ case findAmbig env of+ [] -> pure env+ ambig -> do mapM_ recordError [ OverlappingSyms xs | xs <- ambig ]+ pure (forceUnambig env)++-- | Issue warnings if entries in the first environment would+-- shadow something in the second.+checkShadowing :: NamingEnv -> NamingEnv -> RenameM ()+checkShadowing envNew envOld =+ mapM_ recordWarning+ [ SymbolShadowed p x xs | (p,x,xs) <- findShadowing envNew envOld ]++ -- | Shadow the current naming environment with some more names.+-- XXX: The checks are really confusing shadowNames' :: BindsNames env => EnvCheck -> env -> RenameM a -> RenameM a shadowNames' check names m = do- do env <- liftSupply (defsOf names)- RenameM $+ do env <- liftSupply (defsOf names)+ envOld <- RenameM (roNames <$> ask)+ env1 <- case check of+ CheckNone -> pure env+ CheckOverlap -> checkOverlap env+ CheckAll -> do checkShadowing env envOld+ checkOverlap env+ RenameM do ro <- ask- env' <- sets (checkEnv check env (roNames ro))- let ro' = ro { roNames = env' `shadowing` roNames ro }+ let ro' = ro { roNames = env1 `shadowing` envOld } local ro' (unRenameM m) --- | Generate warnings when the left environment shadows things defined in--- the right. Additionally, generate errors when two names overlap in the--- left environment.-checkEnv :: EnvCheck -> NamingEnv -> NamingEnv -> RW -> (NamingEnv,RW)-checkEnv check (NamingEnv lenv) r rw0- | check == CheckNone = (newEnv,rw0)- | otherwise = (newEnv,rwFin)-- where- newEnv = NamingEnv newMap- (rwFin,newMap) = Map.mapAccumWithKey doNS rw0 lenv -- lenv 1 ns at a time- doNS rw ns = Map.mapAccumWithKey (step ns) rw-- -- namespace, current state, k : parse name, xs : possible entities for k- step ns acc k xs = (acc', case check of- CheckNone -> xs- _ -> [head xs]- -- we've already reported an overlap error,- -- so resolve arbitrarily to the first entry- )- where- acc' = acc- { rwWarnings =- if check == CheckAll- then case Map.lookup k (namespaceMap ns r) of- Just os | [x] <- xs- , let os' = filter (/=x) os- , not (null os') ->- SymbolShadowed k x os' : rwWarnings acc- _ -> rwWarnings acc-- else rwWarnings acc- , rwErrors = rwErrors acc Seq.>< containsOverlap xs- }---- | Check the RHS of a single name rewrite for conflicting sources.-containsOverlap :: [Name] -> Seq.Seq RenamerError-containsOverlap [_] = Seq.empty-containsOverlap [] = panic "Renamer" ["Invalid naming environment"]-containsOverlap ns = Seq.singleton (OverlappingSyms ns)-- recordUse :: Name -> RenameM () recordUse x = RenameM $ sets_ $ \rw -> rw { rwNameUseCount = Map.insertWith (+) x 1 (rwNameUseCount rw) }@@ -306,7 +386,8 @@ addDep x = do cur <- getCurMod deps <- case nameInfo x of- Declared m _ | Just (c,_,i:_) <- modPathCommon cur m ->+ GlobalName _ OrigName { ogModule = m }+ | Just (c,_,i:_) <- modPathCommon cur m -> do mb <- nestedModuleOrig (Nested c i) pure case mb of Just y -> Set.fromList [x,y]@@ -318,25 +399,111 @@ warnUnused :: ModPath -> NamingEnv -> RW -> [RenamerWarning] warnUnused m0 env rw =- map warn+ map UnusedName $ Map.keys $ Map.filterWithKey keep $ rwNameUseCount rw where- warn x = UnusedName x keep nm count = count == 1 && isLocal nm oldNames = Map.findWithDefault Set.empty NSType (visibleNames env)++ -- returns true iff the name comes from a definition in a nested module,+ -- including the current module+ isNestd og = case modPathCommon m0 (ogModule og) of+ Just (_,[],_) | FromDefinition <- ogSource og -> True+ _ -> False+ isLocal nm = case nameInfo nm of- Declared m sys -> sys == UserName &&- m == m0 && nm `Set.notMember` oldNames- Parameter -> True+ GlobalName sys og ->+ sys == UserName && isNestd og && nm `Set.notMember` oldNames+ LocalName {} -> True --- | Get the exported declarations in a module-lookupImport :: Import -> RenameM IfaceDecls-lookupImport imp = RenameM $- do getIf <- roIfaces <$> ask- let ifs = ifPublic (getIf (iModule imp))- sets_ \s -> s { rwExternalDeps = ifs <> rwExternalDeps s }- pure ifs +getExternal :: RenameM (ImpName Name -> Mod ())+getExternal =+ do mp <- roExternal <$> RenameM ask+ pure \nm -> let mb = do t <- case nm of+ ImpTop t -> pure t+ ImpNested x -> nameTopModuleMaybe x+ (_,mp1) <- Map.lookup t mp+ Map.lookup nm mp1+ in case mb of+ Just m -> m+ Nothing -> panic "getExternal"+ ["Missing external name", show (pp nm) ]++getExternalMod :: ImpName Name -> RenameM (Mod ())+getExternalMod nm = ($ nm) <$> getExternal++-- | Returns `Nothing` if the name does not refer to a module (i.e., it is a sig)+getTopModuleIface :: ImpName Name -> RenameM (Maybe Iface)+getTopModuleIface nm =+ do mp <- roExternal <$> RenameM ask+ let t = case nm of+ ImpTop t' -> t'+ ImpNested x -> nameTopModule x+ case Map.lookup t mp of+ Just (mb, _) -> pure mb+ Nothing -> panic "getTopModuleIface"+ ["Missing external module", show (pp nm) ]++{- | Record an import:+ * record external dependency if the name refers to an external import+ * record an error if the imported thing is a functor+-}+recordImport :: Range -> ImpName Name -> RenameM ()+recordImport r i =+ do ro <- RenameM ask+ case Map.lookup i (roResolvedModules ro) of+ Just loc ->+ case rmodKind loc of+ AModule -> pure ()+ k -> recordError (ModuleKindMismatch r i AModule k)+ Nothing ->+ do mb <- getTopModuleIface i+ case mb of+ Nothing -> recordError (ModuleKindMismatch r i AModule ASignature)+ Just iface+ | ifaceIsFunctor iface ->+ recordError (ModuleKindMismatch r i AModule AFunctor)+ | otherwise ->+ RenameM $ sets_ \s -> s { rwExternalDeps = ifDefines iface <>+ rwExternalDeps s }+++-- | Lookup a name either in the locally resolved thing or in an external module+lookupModuleThing :: ImpName Name -> RenameM (Either ResolvedLocal (Mod ()))+lookupModuleThing nm =+ do ro <- RenameM ask+ case Map.lookup nm (roResolvedModules ro) of+ Just loc -> pure (Left loc)+ Nothing -> Right <$> getExternalMod nm++lookupDefines :: ImpName Name -> RenameM NamingEnv+lookupDefines nm =+ do thing <- lookupModuleThing nm+ pure case thing of+ Left loc -> rmodDefines loc+ Right e -> modDefines e++checkIsModule :: Range -> ImpName Name -> ModKind -> RenameM ()+checkIsModule r nm expect =+ do thing <- lookupModuleThing nm+ let actual = case thing of+ Left rmod -> rmodKind rmod+ Right mo -> modKind mo+ unless (actual == expect)+ (recordError (ModuleKindMismatch r nm expect actual))++lookupDefinesAndSubs :: ImpName Name -> RenameM (NamingEnv, Set Name)+lookupDefinesAndSubs nm =+ do thing <- lookupModuleThing nm+ pure case thing of+ Left rmod -> ( rmodDefines rmod, rmodNested rmod)+ Right m ->+ ( modDefines m+ , Set.unions [ Map.keysSet (modMods m)+ , Map.keysSet (modInstances m)+ ]+ )
src/Cryptol/Parser.y view
@@ -38,7 +38,6 @@ import Cryptol.Parser.Token import Cryptol.Parser.ParserUtils import Cryptol.Parser.Unlit(PreProc(..), guessPreProc)-import Cryptol.Utils.Ident(paramInstModName) import Cryptol.Utils.RecordMap(RecordMap) import Paths_cryptol@@ -84,12 +83,14 @@ 'if' { Located $$ (Token (KW KW_if ) _)} 'then' { Located $$ (Token (KW KW_then ) _)} 'else' { Located $$ (Token (KW KW_else ) _)}+ 'interface' { Located $$ (Token (KW KW_interface) _)} 'x' { Located $$ (Token (KW KW_x) _)} 'down' { Located $$ (Token (KW KW_down) _)} 'by' { Located $$ (Token (KW KW_by) _)} 'primitive' { Located $$ (Token (KW KW_primitive) _)} 'constraint'{ Located $$ (Token (KW KW_constraint) _)}+ 'foreign' { Located $$ (Token (KW KW_foreign) _)} 'Prop' { Located $$ (Token (KW KW_Prop) _)} '[' { Located $$ (Token (Sym BracketL) _)}@@ -140,7 +141,7 @@ DOC { $$@(Located _ (Token (White DocStr) _)) } -%name vmodule vmodule+%name top_module top_module %name program program %name programLayout program_layout %name expr expr@@ -164,44 +165,78 @@ %% -vmodule :: { Module PName }- : 'module' module_def { $2 }- | 'v{' vmod_body 'v}' { mkAnonymousModule $2 }-+top_module :: { [Module PName] }+ : 'module' module_def {% mkTopMods $2 }+ | 'v{' vmod_body 'v}' {% mkAnonymousModule $2 }+ | 'interface' 'module' modName 'where' 'v{' sig_body 'v}'+ { mkTopSig $3 $6 } module_def :: { Module PName } : modName 'where'- 'v{' vmod_body 'v}' { mkModule $1 $4 }+ 'v{' vmod_body 'v}' { mkModule $1 $4 } - | modName '=' modName 'where'- 'v{' vmod_body 'v}' { mkModuleInstance $1 $3 $6 }+ | modName '=' impName 'where'+ 'v{' vmod_body 'v}' { mkModuleInstanceAnon $1 $3 $6 } + | modName '=' impName '{' modInstParams '}' { mkModuleInstance $1 $3 $5 }+++modInstParams :: { ModuleInstanceArgs PName }+ : modInstParam { DefaultInstArg $1 }+ | namedModInstParams { NamedInstArgs $1 }++namedModInstParams :: { [ ModuleInstanceNamedArg PName ] }+ : namedModInstParam { [$1] }+ | namedModInstParams ',' namedModInstParam { $3 : $1 }++namedModInstParam :: { ModuleInstanceNamedArg PName }+ : ident '=' modInstParam { ModuleInstanceNamedArg $1 $3 }++modInstParam :: { Located (ModuleInstanceArg PName) }+ : impName { fmap ModuleArg $1 }+ | 'interface' ident { fmap ParameterArg $2 }+ | '_' { Located { thing = AddParams+ , srcRange = $1 } }+ vmod_body :: { [TopDecl PName] } : vtop_decls { reverse $1 } | {- empty -} { [] } --- XXX replace rComb with uses of at++-- inverted+imports1 :: { [ Located (ImportG (ImpName PName)) ] }+ : imports1 'v;' import { $3 : $1 }+ | imports1 ';' import { $3 : $1 }+ | import { [$1] }++ import :: { Located (ImportG (ImpName PName)) }- : 'import' impName mbAs mbImportSpec- { Located { srcRange = rComb $1- $ fromMaybe (srcRange $2)- $ msum [ fmap srcRange $4- , fmap srcRange $3- ]- , thing = Import- { iModule = thing $2- , iAs = fmap thing $3- , iSpec = fmap thing $4- }- } }+ : 'import' impName optInst mbAs mbImportSpec optImportWhere+ {% mkImport $1 $2 $3 $4 $5 $6 }+ | 'import' impNameBT mbAs mbImportSpec {% mkBacktickImport $1 $2 $3 $4 } +optImportWhere :: { Maybe (Located [Decl PName]) }+ : 'where' whereClause { Just $2 }+ | {- empty -} { Nothing }++optInst :: { Maybe (ModuleInstanceArgs PName) }+ : '{' modInstParams '}' { Just $2 }+ | {- empty -} { Nothing }++ impName :: { Located (ImpName PName) } : 'submodule' qname { ImpNested `fmap` $2 } | modName { ImpTop `fmap` $1 } +impNameBT :: { Located (ImpName PName) }+ : 'submodule' '`' qname { ImpNested `fmap` $3 }+ | '`' modName { ImpTop `fmap` $2 } +++ mbAs :: { Maybe (Located ModName) } : 'as' modName { Just $2 } | {- empty -} { Nothing }@@ -216,9 +251,9 @@ | {- empty -} { Nothing } name_list :: { [LIdent] }- : name_list ',' ident { $3 : $1 }- | ident { [$1] }- | {- empty -} { [] }+ : name_list ',' var { fmap getIdent $3 : $1 }+ | var { [fmap getIdent $1] }+ | {- empty -} { [] } mbHiding :: { [Ident] -> ImportSpec } : 'hiding' { Hiding }@@ -251,12 +286,40 @@ { [exportDecl $1 Public (mkProperty $3 [] $5)] } | mbDoc newtype { [exportNewtype Public $1 $2] } | prim_bind { $1 }+ | foreign_bind { $1 } | private_decls { $1 }- | parameter_decls { $1 }+ | mbDoc 'interface' 'constraint' type {% mkInterfaceConstraint $1 $4 }+ | parameter_decls { [ $1 ] } | mbDoc 'submodule' module_def {% ((:[]) . exportModule $1) `fmap` mkNested $3 }- | import { [DImport $1] } + | mbDoc sig_def { [mkSigDecl $1 $2] }+ | mod_param_decl { [DModParam $1] }+ | mbDoc import { [DImport $2] }+ -- we allow for documentation here to avoid conflicts with module paramaters+ -- currently that odcumentation is just discarded+++sig_def :: { (Located PName, Signature PName) }+ : 'interface' 'submodule' name 'where' 'v{' sig_body 'v}'+ { ($3, $6) }++sig_body :: { Signature PName }+ : par_decls {% mkInterface [] $1 }+ | imports1 'v;' par_decls {% mkInterface (reverse $1) $3 }+ | imports1 ';' par_decls {% mkInterface (reverse $1) $3 }+++mod_param_decl :: { ModParam PName }+ : mbDoc+ 'import' 'interface'+ impName mbAs { ModParam { mpSignature = $4+ , mpAs = fmap thing $5+ , mpName = mkModParamName $4 $5+ , mpDoc = $1+ , mpRenaming = mempty } }++ top_decl :: { [TopDecl PName] } : decl { [Decl (TopLevel {tlExport = Public, tlValue = $1 })] } | 'include' STRLIT {% (return . Include) `fmap` fromStrLit $2 }@@ -273,22 +336,24 @@ | mbDoc 'primitive' '(' op ')' ':' schema { mkPrimDecl $1 $4 $7 } | mbDoc 'primitive' 'type' schema ':' kind {% mkPrimTypeDecl $1 $4 $6 } +foreign_bind :: { [TopDecl PName] }+ : mbDoc 'foreign' name ':' schema {% mkForeignDecl $1 $3 $5 } -parameter_decls :: { [TopDecl PName] }- : 'parameter' 'v{' par_decls 'v}' { reverse $3 }- | doc 'parameter' 'v{' par_decls 'v}' { reverse $4 }+parameter_decls :: { TopDecl PName }+ : 'parameter' 'v{' par_decls 'v}' { mkParDecls (reverse $3) }+ | doc 'parameter' 'v{' par_decls 'v}' { mkParDecls (reverse $4) } -- Reversed-par_decls :: { [TopDecl PName] }+par_decls :: { [ParamDecl PName] } : par_decl { [$1] } | par_decls ';' par_decl { $3 : $1 } | par_decls 'v;' par_decl { $3 : $1 } -par_decl :: { TopDecl PName }+par_decl :: { ParamDecl PName } : mbDoc name ':' schema { mkParFun $1 $2 $4 } | mbDoc 'type' name ':' kind {% mkParType $1 $3 $5 }- | mbDoc 'type' 'constraint' type {% fmap (DParameterConstraint . distrLoc)- (mkProp $4) }+ | mbDoc typeOrPropSyn { mkIfacePropSyn (thing `fmap` $1) $2 }+ | mbDoc topTypeConstraint { DParameterConstraint (distrLoc $2) } doc :: { Located Text }@@ -298,11 +363,14 @@ : doc { Just $1 } | {- empty -} { Nothing } - decl :: { Decl PName } : vars_comma ':' schema { at (head $1,$3) $ DSignature (reverse $1) $3 } | ipat '=' expr { at ($1,$3) $ DPatBind $1 $3 } | '(' op ')' '=' expr { at ($1,$5) $ DPatBind (PVar $2) $5 }+ | var apats_indices propguards_cases+ {% mkPropGuardsDecl $1 $2 $3 }+ | var propguards_cases+ {% mkConstantPropGuardsDecl $1 $2 } | var apats_indices '=' expr { at ($1,$4) $ mkIndexedDecl $1 $2 $4 } @@ -320,18 +388,7 @@ , bExport = Public } } - | 'type' name '=' type {% at ($1,$4) `fmap` mkTySyn $2 [] $4 }- | 'type' name tysyn_params '=' type- {% at ($1,$5) `fmap` mkTySyn $2 (reverse $3) $5 }- | 'type' tysyn_param op tysyn_param '=' type- {% at ($1,$6) `fmap` mkTySyn $3 [$2, $4] $6 }-- | 'type' 'constraint' name '=' type- {% at ($2,$5) `fmap` mkPropSyn $3 [] $5 }- | 'type' 'constraint' name tysyn_params '=' type- {% at ($2,$6) `fmap` mkPropSyn $3 (reverse $4) $6 }- | 'type' 'constraint' tysyn_param op tysyn_param '=' type- {% at ($2,$7) `fmap` mkPropSyn $4 [$3, $5] $7 }+ | typeOrPropSyn { $1 } | 'infixl' NUM ops {% mkFixity LeftAssoc $2 (reverse $3) } | 'infixr' NUM ops {% mkFixity RightAssoc $2 (reverse $3) }@@ -363,30 +420,35 @@ | 'let' vars_comma ':' schema { at (head $2,$4) $ DSignature (reverse $2) $4 } - | 'type' name '=' type {% at ($1,$4) `fmap` mkTySyn $2 [] $4 }- | 'type' name tysyn_params '=' type- {% at ($1,$5) `fmap` mkTySyn $2 (reverse $3) $5 }- | 'type' tysyn_param op tysyn_param '=' type- {% at ($1,$6) `fmap` mkTySyn $3 [$2, $4] $6 }-- | 'type' 'constraint' name '=' type- {% at ($2,$5) `fmap` mkPropSyn $3 [] $5 }- | 'type' 'constraint' name tysyn_params '=' type- {% at ($2,$6) `fmap` mkPropSyn $3 (reverse $4) $6 }- | 'type' 'constraint' tysyn_param op tysyn_param '=' type- {% at ($2,$7) `fmap` mkPropSyn $4 [$3, $5] $7 }+ | typeOrPropSyn { $1 } | 'infixl' NUM ops {% mkFixity LeftAssoc $2 (reverse $3) } | 'infixr' NUM ops {% mkFixity RightAssoc $2 (reverse $3) } | 'infix' NUM ops {% mkFixity NonAssoc $2 (reverse $3) } -newtype :: { Newtype PName }- : 'newtype' qname '=' newtype_body- { Newtype $2 [] (thing $4) }- | 'newtype' qname tysyn_params '=' newtype_body- { Newtype $2 (reverse $3) (thing $5) }+typeOrPropSyn :: { Decl PName }+ : 'type' 'constraint' type '=' type {% mkPropSyn $3 $5 }+ | 'type' type '=' type {% mkTySyn $2 $4 } +topTypeConstraint :: { Located [Prop PName] }+ : 'type' 'constraint' type {% mkProp $3 }+++propguards_cases :: { [PropGuardCase PName] }+ : propguards_cases propguards_case { $2 : $1 }+ | propguards_case { [$1] }++propguards_case :: { PropGuardCase PName }+ : '|' propguards_quals '=>' expr { PropGuardCase $2 $4 }++propguards_quals :: { [Located (Prop PName)] }+ : type {% mkPropGuards $1 }+++newtype :: { Newtype PName }+ : 'newtype' type '=' newtype_body {% mkNewtype $2 $4 }+ newtype_body :: { Located (RecordMap Ident (Range, Type PName)) } : '{' '}' {% mkRecord (rComb $1 $2) (Located emptyRange) [] } | '{' field_types '}' {% mkRecord (rComb $1 $3) (Located emptyRange) $2 }@@ -516,13 +578,13 @@ : expr 'then' expr { ($1, $3) } simpleRHS :: { Expr PName }- : '-' simpleApp { at ($1,$2) (ENeg $2) }- | '~' simpleApp { at ($1,$2) (EComplement $2) }+ : '-' simpleApp { at ($1,$2) (EPrefix PrefixNeg $2) }+ | '~' simpleApp { at ($1,$2) (EPrefix PrefixComplement $2) } | simpleApp { $1 } longRHS :: { Expr PName }- : '-' longApp { at ($1,$2) (ENeg $2) }- | '~' longApp { at ($1,$2) (EComplement $2) }+ : '-' longApp { at ($1,$2) (EPrefix PrefixNeg $2) }+ | '~' longApp { at ($1,$2) (EPrefix PrefixComplement $2) } | longApp { $1 } @@ -720,14 +782,6 @@ : schema_param { [$1] } | schema_params ',' schema_param { $3 : $1 } -tysyn_param :: { TParam PName }- : ident {% mkTParam $1 Nothing }- | '(' ident ':' kind ')' {% mkTParam (at ($1,$5) $2) (Just (thing $4)) }--tysyn_params :: { [TParam PName] }- : tysyn_param { [$1] }- | tysyn_params tysyn_param { $2 : $1 }- type :: { Type PName } : infix_type '->' type { at ($1,$3) $ TFun $1 $3 } | infix_type { $1 }@@ -748,13 +802,17 @@ | NUM { at $1 $ TNum (getNum $1) } | CHARLIT { at $1 $ TChar (getChr $1) } | '[' type ']' { at ($1,$3) $ TSeq $2 TBit }- | '(' type ')' { at ($1,$3) $ TParens $2 }+ | '(' ktype ')' { at ($1,$3) $2 } | '(' ')' { at ($1,$2) $ TTuple [] } | '(' tuple_types ')' { at ($1,$3) $ TTuple (reverse $2) } | '{' '}' {% mkRecord (rComb $1 $2) TRecord [] } | '{' field_types '}' {% mkRecord (rComb $1 $3) TRecord $2 } | '_' { at $1 TWild } +ktype :: { Type PName }+ : type ':' kind { TParens $1 (Just (thing $3)) }+ | type { TParens $1 Nothing }+ atypes :: { [ Type PName ] } : atype { [ $1 ] } | atypes atype { $2 : $1 }@@ -795,8 +853,7 @@ modName :: { Located ModName } : smodName { $1 }- | '`' smodName { fmap paramInstModName $2 }-+ | 'module' smodName { $2 } qname :: { Located PName } : name { $1 }@@ -860,8 +917,8 @@ Layout -> programLayout NoLayout -> program -parseModule :: Config -> Text -> Either ParseError (Module PName)-parseModule cfg = parse cfg { cfgModuleScope = True } vmodule+parseModule :: Config -> Text -> Either ParseError [Module PName]+parseModule cfg = parse cfg { cfgModuleScope = True } top_module parseProgram :: Layout -> Text -> Either ParseError (Program PName) parseProgram l = parseProgramWith defaultConfig { cfgLayout = l }
src/Cryptol/Parser/AST.hs view
@@ -16,6 +16,8 @@ {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE FlexibleInstances #-} module Cryptol.Parser.AST ( -- * Names Ident, mkIdent, mkInfix, isInfixIdent, nullIdent, identText@@ -39,8 +41,20 @@ -- * Declarations , Module , ModuleG(..)+ , mDecls -- XXX: Temporary+ , mImports- , mSubmoduleImports+ , mModParams+ , mIsFunctor+ , isParamDecl++ , ModuleDefinition(..)+ , ModuleInstanceArgs(..)+ , ModuleInstanceNamedArg(..)+ , ModuleInstanceArg(..)+ , ModuleInstance+ , emptyModuleInstance+ , Program(..) , TopDecl(..) , Decl(..)@@ -59,6 +73,11 @@ , ParameterType(..) , ParameterFun(..) , NestedModule(..)+ , Signature(..)+ , SigDecl(..)+ , ModParam(..)+ , ParamDecl(..)+ , PropGuardCase(..) -- * Interactive , ReplInput(..)@@ -74,6 +93,9 @@ , UpdHow(..) , FunDesc(..) , emptyFunDesc+ , PrefixOp(..)+ , prefixFixity+ , asEApps -- * Positions , Located(..)@@ -92,9 +114,11 @@ import Cryptol.Utils.RecordMap import Cryptol.Utils.PP +import Data.Map(Map)+import qualified Data.Map as Map import Data.List(intersperse) import Data.Bits(shiftR)-import Data.Maybe (catMaybes)+import Data.Maybe (catMaybes,mapMaybe) import Data.Ratio(numerator,denominator) import Data.Text (Text) import Numeric(showIntAtBase,showFloat,showHFloat)@@ -122,36 +146,85 @@ newtype Program name = Program [TopDecl name] deriving (Show) --- | A parsed module.+{- | A module for the pre-typechecker phasese. The two parameters are:++ * @mname@ the type of module names. This is because top-level and nested+ modules use differnt types to identify a module.++ * @name@ the type of identifiers used by declarations.+ In the parser this starts off as `PName` and after resolving names+ in the renamer, this becomes `Name`.+-} data ModuleG mname name = Module { mName :: Located mname -- ^ Name of the module- , mInstance :: !(Maybe (Located ModName)) -- ^ Functor to instantiate- -- (if this is a functor instnaces)- -- , mImports :: [Located Import] -- ^ Imports for the module- , mDecls :: [TopDecl name] -- ^ Declartions for the module+ , mDef :: ModuleDefinition name } deriving (Show, Generic, NFData) ++-- | Different flavours of module we have.+data ModuleDefinition name =+ NormalModule [TopDecl name]++ | FunctorInstance (Located (ImpName name))+ (ModuleInstanceArgs name)+ (ModuleInstance name)+ -- ^ The instance is filled in by the renamer++ | InterfaceModule (Signature name)+ deriving (Show, Generic, NFData)++{- | Maps names in the original functor with names in the instnace.+Does *NOT* include the parameters, just names for the definitions.+This *DOES* include entrirs for all the name in the instantiated functor,+including names in modules nested inside the functor. -}+type ModuleInstance name = Map name name++emptyModuleInstance :: Ord name => ModuleInstance name+emptyModuleInstance = mempty+++-- XXX: Review all places this is used, that it actually makes sense+-- Probably shouldn't exist+mDecls :: ModuleG mname name -> [TopDecl name]+mDecls m =+ case mDef m of+ NormalModule ds -> ds+ FunctorInstance _ _ _ -> []+ InterfaceModule {} -> []++-- | Imports of top-level (i.e. "file" based) modules. mImports :: ModuleG mname name -> [ Located Import ] mImports m =- [ li { thing = i { iModule = n } }- | DImport li <- mDecls m- , let i = thing li- , ImpTop n <- [iModule i]- ]+ case mDef m of+ NormalModule ds -> mapMaybe topImp [ li | DImport li <- ds ]+ FunctorInstance {} -> []+ InterfaceModule sig -> mapMaybe topImp (sigImports sig)+ where+ topImp li = case iModule i of+ ImpTop n -> Just li { thing = i { iModule = n } }+ _ -> Nothing+ where i = thing li -mSubmoduleImports :: ModuleG mname name -> [ Located (ImportG name) ]-mSubmoduleImports m =- [ li { thing = i { iModule = n } }- | DImport li <- mDecls m- , let i = thing li- , ImpNested n <- [iModule i]- ] +-- | Get the module parameters of a module (new module system)+mModParams :: ModuleG mname name -> [ ModParam name ]+mModParams m = [ p | DModParam p <- mDecls m ] +mIsFunctor :: ModuleG mname nmae -> Bool+mIsFunctor m = any isParamDecl (mDecls m) -type Module = ModuleG ModName+isParamDecl :: TopDecl a -> Bool+isParamDecl d =+ case d of+ DModParam {} -> True+ DParamDecl {} -> True+ _ -> False +-- | A top-level module+type Module = ModuleG ModName++-- | A nested module. newtype NestedModule name = NestedModule (ModuleG name name) deriving (Show,Generic,NFData) @@ -164,39 +237,110 @@ , Just (Range { from = start, to = start, source = "" }) ] -+-- | A declaration that may only appear at the top level of a module.+-- The module may be nested, however. data TopDecl name = Decl (TopLevel (Decl name)) | DPrimType (TopLevel (PrimType name)) | TDNewtype (TopLevel (Newtype name)) -- ^ @newtype T as = t- | Include (Located FilePath) -- ^ @include File@- | DParameterType (ParameterType name) -- ^ @parameter type T : #@- | DParameterConstraint [Located (Prop name)]- -- ^ @parameter type constraint (fin T)@+ | Include (Located FilePath) -- ^ @include File@ (until NoInclude)++ | DParamDecl Range (Signature name) -- ^ @parameter ...@ (parser only)++ | DModule (TopLevel (NestedModule name)) -- ^ @submodule M where ...@+ | DImport (Located (ImportG (ImpName name))) -- ^ @import X@+ | DModParam (ModParam name) -- ^ @import interface X ...@+ | DInterfaceConstraint (Maybe Text) (Located [Prop name])+ -- ^ @interface constraint@+ deriving (Show, Generic, NFData)+++-- | Things that maybe appear in an interface/parameter block.+-- These only exist during parsering.+data ParamDecl name =++ DParameterType (ParameterType name) -- ^ @parameter type T : #@ (parser only) | DParameterFun (ParameterFun name) -- ^ @parameter someVal : [256]@- | DModule (TopLevel (NestedModule name)) -- ^ Nested module- | DImport (Located (ImportG (ImpName name))) -- ^ An import declaration- deriving (Show, Generic, NFData)+ -- (parser only) -data ImpName name =- ImpTop ModName- | ImpNested name+ | DParameterDecl (SigDecl name) -- ^ A delcaration in an interface++ | DParameterConstraint [Located (Prop name)]+ -- ^ @parameter type constraint (fin T)@+ deriving (Show, Generic, NFData) ++-- | All arguments in a functor instantiation+data ModuleInstanceArgs name =+ DefaultInstArg (Located (ModuleInstanceArg name))+ -- ^ Single parameter instantitaion++ | DefaultInstAnonArg [TopDecl name]+ -- ^ Single parameter instantitaion using this anonymous module.+ -- (parser only)++ | NamedInstArgs [ModuleInstanceNamedArg name]++ deriving (Show, Generic, NFData)++-- | A named argument in a functor instantiation+data ModuleInstanceNamedArg name =+ ModuleInstanceNamedArg (Located Ident) (Located (ModuleInstanceArg name))+ deriving (Show, Generic, NFData)++-- | An argument in a functor instantiation+data ModuleInstanceArg name =+ ModuleArg (ImpName name) -- ^ An argument that is a module+ | ParameterArg Ident -- ^ An argument that is a parameter+ | AddParams -- ^ Arguments adds extra parameters to decls.+ -- ("backtick" import)+ deriving (Show, Generic, NFData)+++-- | The name of an imported module+data ImpName name =+ ImpTop ModName -- ^ A top-level module+ | ImpNested name -- ^ The module in scope with the given name+ deriving (Show, Generic, NFData, Eq, Ord)++-- | A simple declaration. Generally these are things that can appear+-- both at the top-level of a module and in `where` clauses. data Decl name = DSignature [Located name] (Schema name)+ -- ^ A type signature. Eliminated in NoPat--after NoPat+ -- signatures are in their associated Bind+ | DFixity !Fixity [Located name]+ -- ^ A fixity declaration. Eliminated in NoPat---after NoPat+ -- fixities are in their associated Bind+ | DPragma [Located name] Pragma+ -- ^ A pragma declaration. Eliminated in NoPat---after NoPat+ -- fixities are in their associated Bind+ | DBind (Bind name)+ -- ^ A non-recursive binding.+ | DRec [Bind name]- -- ^ A group of recursive bindings, introduced by the renamer.+ -- ^ A group of recursive bindings. Introduced by the renamer.+ | DPatBind (Pattern name) (Expr name)+ -- ^ A pattern binding. Eliminated in NoPat---after NoPat+ -- fixities are in their associated Bind+ | DType (TySyn name)+ -- ^ A type synonym.+ | DProp (PropSyn name)+ -- ^ A constraint synonym.+ | DLocated (Decl name) Range+ -- ^ Keeps track of the location of a declaration.+ deriving (Eq, Show, Generic, NFData, Functor) --- | A type parameter+-- | A type parameter for a module. data ParameterType name = ParameterType { ptName :: Located name -- ^ name of type parameter , ptKind :: Kind -- ^ kind of parameter@@ -205,7 +349,7 @@ , ptNumber :: !Int -- ^ number of the parameter } deriving (Eq,Show,Generic,NFData) --- | A value parameter+-- | A value parameter for a module. data ParameterFun name = ParameterFun { pfName :: Located name -- ^ name of value parameter , pfSchema :: Schema name -- ^ schema for parameter@@ -214,12 +358,67 @@ } deriving (Eq,Show,Generic,NFData) +{- | Interface Modules (aka types of functor arguments)++IMPORTANT: Interface Modules are a language construct and are different from+the notion of "interface" in the Cryptol implementation.++Note that the names *defined* in an interface module are only really used in the+other members of the interface module. When an interface module is "imported"+as a functor parameter these names are instantiated to new names,+because there could be multiple paramers using the same interface. -}+data Signature name = Signature+ { sigImports :: ![Located (ImportG (ImpName name))]+ -- ^ Add things in scope+ , sigTypeParams :: [ParameterType name] -- ^ Type parameters+ , sigConstraints :: [Located (Prop name)]+ -- ^ Constraints on the type parameters and type synonyms.+ , sigDecls :: [SigDecl name]+ -- ^ Type and constraint synonyms+ , sigFunParams :: [ParameterFun name] -- ^ Value parameters+ } deriving (Show,Generic,NFData)++-- | A constraint or type synonym declared in an interface.+data SigDecl name =+ SigTySyn (TySyn name) (Maybe Text)+ | SigPropSyn (PropSyn name) (Maybe Text)+ deriving (Show,Generic,NFData)++{- | A module parameter declaration.++> import interface A+> import interface A as B++The name of the parameter is derived from the `as` clause. If there+is no `as` clause then it is derived from the name of the interface module.++If there is no `as` clause, then the type/value parameters are unqualified,+and otherwise they are qualified.+-}+data ModParam name = ModParam+ { mpSignature :: Located (ImpName name) -- ^ Signature for parameter+ , mpAs :: Maybe ModName -- ^ Qualified for actual params+ , mpName :: !Ident+ {- ^ Parameter name (for inst.)+ Note that this is not resolved in the renamer, and is only used+ when instantiating a functor. -}++ , mpDoc :: Maybe (Located Text) -- ^ Optional documentation+ , mpRenaming :: !(Map name name)+ {- ^ Filled in by the renamer.+ Maps the actual (value/type) parameter names to the names in the+ interface module. -}+ } deriving (Eq,Show,Generic,NFData)++ -- | An import declaration. data ImportG mname = Import { iModule :: !mname , iAs :: Maybe ModName , iSpec :: Maybe ImportSpec- } deriving (Eq, Show, Generic, NFData)+ , iInst :: !(Maybe (ModuleInstanceArgs PName))+ -- ^ `iInst' exists only during parsing+ } deriving (Show, Generic, NFData) type Import = ImportG ModName @@ -276,17 +475,27 @@ type LBindDef = Located (BindDef PName) data BindDef name = DPrim+ | DForeign | DExpr (Expr name)+ | DPropGuards [PropGuardCase name] deriving (Eq, Show, Generic, NFData, Functor) +data PropGuardCase name = PropGuardCase+ { pgcProps :: [Located (Prop name)]+ , pgcExpr :: Expr name+ }+ deriving (Eq,Generic,NFData,Functor,Show)+ data Pragma = PragmaNote String | PragmaProperty deriving (Eq, Show, Generic, NFData) -data Newtype name = Newtype { nName :: Located name -- ^ Type name- , nParams :: [TParam name] -- ^ Type params- , nBody :: Rec (Type name) -- ^ Body- } deriving (Eq, Show, Generic, NFData)+data Newtype name = Newtype+ { nName :: Located name -- ^ Type name+ , nParams :: [TParam name] -- ^ Type params+ , nConName :: !name -- ^ Constructor function name+ , nBody :: Rec (Type name) -- ^ Body+ } deriving (Eq, Show, Generic, NFData) -- | A declaration for a type with no implementation. data PrimType name = PrimType { primTName :: Located name@@ -341,8 +550,6 @@ data Expr n = EVar n -- ^ @ x @ | ELit Literal -- ^ @ 0x10 @- | ENeg (Expr n) -- ^ @ -1 @- | EComplement (Expr n) -- ^ @ ~1 @ | EGenerate (Expr n) -- ^ @ generate f @ | ETuple [Expr n] -- ^ @ (1,2,3) @ | ERecord (Rec (Expr n)) -- ^ @ { x = 1, y = 2 } @@@ -373,8 +580,20 @@ | ESplit (Expr n) -- ^ @ splitAt x @ (Introduced by NoPat) | EParens (Expr n) -- ^ @ (e) @ (Removed by Fixity) | EInfix (Expr n) (Located n) Fixity (Expr n)-- ^ @ a + b @ (Removed by Fixity)+ | EPrefix PrefixOp (Expr n) -- ^ @ -1, ~1 @ deriving (Eq, Show, Generic, NFData, Functor) +-- | Prefix operator.+data PrefixOp = PrefixNeg -- ^ @ - @+ | PrefixComplement -- ^ @ ~ @+ deriving (Eq, Show, Generic, NFData)++prefixFixity :: PrefixOp -> Fixity+prefixFixity op = Fixity { fAssoc = LeftAssoc, .. }+ where fLevel = case op of+ PrefixNeg -> 80+ PrefixComplement -> 100+ -- | Description of functions. Only trivial information is provided here -- by the parser. The NoPat pass fills this in as required. data FunDesc n =@@ -439,7 +658,7 @@ | TTuple [Type n] -- ^ @([8], [32])@ | TWild -- ^ @_@, just some type. | TLocated (Type n) Range -- ^ Location information- | TParens (Type n) -- ^ @ (ty) @+ | TParens (Type n) (Maybe Kind) -- ^ @ (ty) @ | TInfix (Type n) (Located n) Fixity (Type n) -- ^ @ ty + ty @ deriving (Eq, Show, Generic, NFData, Functor) @@ -530,12 +749,29 @@ DPrimType pt -> getLoc pt TDNewtype n -> getLoc n Include lfp -> getLoc lfp+ DModule d -> getLoc d+ DImport d -> getLoc d+ DModParam d -> getLoc d+ DParamDecl r _ -> Just r+ DInterfaceConstraint _ ds -> getLoc ds++instance HasLoc (ParamDecl name) where+ getLoc pd =+ case pd of DParameterType d -> getLoc d DParameterFun d -> getLoc d+ DParameterDecl d -> getLoc d DParameterConstraint d -> getLoc d- DModule d -> getLoc d- DImport d -> getLoc d +instance HasLoc (SigDecl name) where+ getLoc decl =+ case decl of+ SigTySyn ts _ -> getLoc ts+ SigPropSyn ps _ -> getLoc ps++instance HasLoc (ModParam name) where+ getLoc mp = getLoc (mpSignature mp)+ instance HasLoc (PrimType name) where getLoc pt = Just (rComb (srcRange (primTName pt)) (srcRange (primTKind pt))) @@ -565,7 +801,14 @@ where locs = catMaybes ([ getLoc (nName n)] ++ map (Just . fst . snd) (displayFields (nBody n))) +instance HasLoc (TySyn name) where+ getLoc (TySyn x _ _ _) = getLoc x +instance HasLoc (PropSyn name) where+ getLoc (PropSyn x _ _ _) = getLoc x+++ -------------------------------------------------------------------------------- @@ -588,22 +831,56 @@ instance (Show name, PPName mname, PPName name) => PP (ModuleG mname name) where- ppPrec _ = ppModule 0+ ppPrec _ = ppModule "module" +instance (Show name, PPName name) => PP (NestedModule name) where+ ppPrec _ (NestedModule m) = ppModule "submodule" m+ ppModule :: (Show name, PPName mname, PPName name) =>- Int -> ModuleG mname name -> Doc-ppModule n m =- text "module" <+> ppL (mName m) <+> text "where" $$ nest n body+ Doc -> ModuleG mname name -> Doc+ppModule kw m = kw' <+> ppL (mName m) <+> pp (mDef m) where- body = vcat (map ppL (mImports m))- $$ vcat (map pp (mDecls m))+ kw' = case mDef m of+ InterfaceModule {} -> "interface" <+> kw+ _ -> kw +instance (Show name, PPName name) => PP (ModuleDefinition name) where+ ppPrec _ def =+ case def of+ NormalModule ds -> "where" $$ indent 2 (vcat (map pp ds))+ FunctorInstance f as inst -> vcat ( ("=" <+> pp (thing f) <+> pp as)+ : ppInst+ )+ where+ ppInst = if null inst then [] else [ indent 2+ (vcat ("/* Instance:" :+ instLines ++ [" */"]))+ ]+ instLines = [ " *" <+> pp k <+> "->" <+> pp v+ | (k,v) <- Map.toList inst ]+ InterfaceModule s -> ppInterface "where" s -instance (Show name, PPName name) => PP (NestedModule name) where- ppPrec _ (NestedModule m) = ppModule 2 m +instance (Show name, PPName name) => PP (ModuleInstanceArgs name) where+ ppPrec _ arg =+ case arg of+ DefaultInstArg x -> braces (pp (thing x))+ DefaultInstAnonArg ds -> "where" $$ indent 2 (vcat (map pp ds))+ NamedInstArgs xs -> braces (commaSep (map pp xs)) +instance (Show name, PPName name) => PP (ModuleInstanceNamedArg name) where+ ppPrec _ (ModuleInstanceNamedArg x y) = pp (thing x) <+> "=" <+> pp (thing y)+++instance (Show name, PPName name) => PP (ModuleInstanceArg name) where+ ppPrec _ arg =+ case arg of+ ModuleArg x -> pp x+ ParameterArg i -> "parameter" <+> pp i+ AddParams -> "{}"++ instance (Show name, PPName name) => PP (Program name) where ppPrec _ (Program ds) = vcat (map pp ds) @@ -614,27 +891,77 @@ DPrimType p -> pp p TDNewtype n -> pp n Include l -> text "include" <+> text (show (thing l))+ DModule d -> pp d+ DImport i -> pp (thing i)+ DModParam s -> pp s+ DParamDecl _ ds -> ppInterface "parameter" ds+ DInterfaceConstraint _ ds ->+ "interface constraint" <+>+ case map pp (thing ds) of+ [x] -> x+ [] -> "()"+ xs -> nest 1 (parens (commaSepFill xs))++instance (Show name, PPName name) => PP (ParamDecl name) where+ ppPrec _ pd =+ case pd of DParameterFun d -> pp d DParameterType d -> pp d+ DParameterDecl d -> pp d DParameterConstraint d ->- "parameter" <+> "type" <+> "constraint" <+> prop- where prop = case map (pp . thing) d of- [x] -> x- [] -> "()"- xs -> nest 1 (parens (commaSepFill xs))- DModule d -> pp d- DImport i -> pp (thing i)+ "type constraint" <+> parens (commaSep (map (pp . thing) d)) +ppInterface :: (Show name, PPName name) => Doc -> Signature name -> Doc+ppInterface kw sig = kw $$ indent 2 (vcat (is ++ ds))+ where+ is = map pp (sigImports sig)+ cs = case sigConstraints sig of+ [] -> []+ cs' -> ["type constraint" <+>+ parens (commaSep (map (pp . thing) cs'))]+ ds = map pp (sigTypeParams sig)+ ++ map pp (sigDecls sig)+ ++ cs+ ++ map pp (sigFunParams sig)++instance (Show name, PPName name) => PP (SigDecl name) where+ ppPrec p decl =+ case decl of+ SigTySyn ts _ -> ppPrec p ts+ SigPropSyn ps _ -> ppPrec p ps+++instance (Show name, PPName name) => PP (ModParam name) where+ ppPrec _ mp = vcat ( mbDoc+ ++ [ "import interface" <+>+ pp (thing (mpSignature mp)) <+> mbAs ]+ ++ mbRen+ )+ where+ mbDoc = case mpDoc mp of+ Nothing -> []+ Just d -> [pp d]+ mbAs = case mpAs mp of+ Nothing -> mempty+ Just d -> "as" <+> pp d+ mbRen+ | Map.null (mpRenaming mp) = []+ | otherwise =+ [ indent 2 $ vcat $ "/* Parameters"+ : [ " *" <+> pp x <+> "->" <+> pp y+ | (x,y) <- Map.toList (mpRenaming mp) ]+ ++ [" */"] ]+ instance (Show name, PPName name) => PP (PrimType name) where ppPrec _ pt = "primitive" <+> "type" <+> pp (primTName pt) <+> ":" <+> pp (primTKind pt) instance (Show name, PPName name) => PP (ParameterType name) where- ppPrec _ a = text "parameter" <+> text "type" <+>+ ppPrec _ a = text "type" <+> ppPrefixName (ptName a) <+> text ":" <+> pp (ptKind a) instance (Show name, PPName name) => PP (ParameterFun name) where- ppPrec _ a = text "parameter" <+> ppPrefixName (pfName a) <+> text ":"+ ppPrec _ a = ppPrefixName (pfName a) <+> text ":" <+> pp (pfSchema a) @@ -662,11 +989,23 @@ , ppRecord (map (ppNamed' ":") (displayFields (nBody nt))) ] -instance PP mname => PP (ImportG mname) where- ppPrec _ d = text "import" <+> sep ([pp (iModule d)] ++ mbAs ++ mbSpec)+instance (PP mname) => PP (ImportG mname) where+ ppPrec _ d = vcat [ text "import" <+> sep ([pp (iModule d)] ++ mbInst +++ mbAs ++ mbSpec)+ , indent 2 mbWhere+ ] where mbAs = maybe [] (\ name -> [text "as" <+> pp name]) (iAs d) mbSpec = maybe [] (\x -> [pp x]) (iSpec d)+ mbInst = case iInst d of+ Just (DefaultInstArg x) -> [ braces (pp (thing x)) ]+ Just (NamedInstArgs xs) -> [ braces (commaSep (map pp xs)) ]+ _ -> []+ mbWhere = case iInst d of+ Just (DefaultInstAnonArg ds) ->+ "where" $$ vcat (map pp ds)+ _ -> mempty+ instance PP name => PP (ImpName name) where ppPrec _ nm =@@ -713,7 +1052,9 @@ instance (Show name, PPName name) => PP (BindDef name) where ppPrec _ DPrim = text "<primitive>"+ ppPrec _ DForeign = text "<foreign>" ppPrec p (DExpr e) = ppPrec p e+ ppPrec _p (DPropGuards _guards) = text "propguards" instance PPName name => PP (TySyn name) where@@ -816,8 +1157,6 @@ EVar x -> ppPrefixName x ELit x -> pp x - ENeg x -> wrap n 3 (text "-" <.> ppPrec 4 x)- EComplement x -> wrap n 3 (text "~" <.> ppPrec 4 x) EGenerate x -> wrap n 3 (text "generate" <+> ppPrec 4 x) ETuple es -> parens (commaSep (map pp es))@@ -877,12 +1216,19 @@ EParens e -> parens (pp e) + -- NOTE: these don't produce correctly parenthesized expressions without+ -- explicit EParens nodes when necessary, since we don't check the actual+ -- fixities of the operators. EInfix e1 op _ e2 -> wrap n 0 (pp e1 <+> ppInfixName (thing op) <+> pp e2)++ EPrefix op e -> wrap n 3 (text (prefixText op) <.> ppPrec 4 e) where isInfix (EApp (EApp (EVar ieOp) ieLeft) ieRight) = do ieFixity <- ppNameFixity ieOp return Infix { .. } isInfix _ = Nothing+ prefixText PrefixNeg = "-"+ prefixText PrefixComplement = "~" instance (Show name, PPName name) => PP (UpdField name) where ppPrec _ (UpdField h xs e) = ppNestedSels (map thing xs) <+> pp h <+> pp e@@ -963,7 +1309,10 @@ TLocated t _ -> ppPrec n t - TParens t -> parens (pp t)+ TParens t mb -> parens+ case mb of+ Nothing -> pp t+ Just k -> pp t <+> ":" <+> pp k TInfix t1 o _ t2 -> optParens (n > 2) $ sep [ppPrec 2 t1 <+> ppInfixName o, ppPrec 3 t2]@@ -972,6 +1321,8 @@ instance PPName name => PP (Prop name) where ppPrec n (CType t) = ppPrec n t +instance PPName name => PP [Prop name] where+ ppPrec n props = parens . commaSep . fmap (ppPrec n) $ props -------------------------------------------------------------------------------- -- Drop all position information, so equality reflects program structure@@ -1000,10 +1351,27 @@ instance NoPos (ModuleG mname name) where noPos m = Module { mName = mName m- , mInstance = mInstance m- , mDecls = noPos (mDecls m)+ , mDef = noPos (mDef m) } +instance NoPos (ModuleDefinition name) where+ noPos m =+ case m of+ NormalModule ds -> NormalModule (noPos ds)+ FunctorInstance f as ds -> FunctorInstance (noPos f) (noPos as) ds+ InterfaceModule s -> InterfaceModule (noPos s)++instance NoPos (ModuleInstanceArgs name) where+ noPos as =+ case as of+ DefaultInstArg a -> DefaultInstArg (noPos a)+ DefaultInstAnonArg ds -> DefaultInstAnonArg (noPos ds)+ NamedInstArgs xs -> NamedInstArgs (noPos xs)++instance NoPos (ModuleInstanceNamedArg name) where+ noPos (ModuleInstanceNamedArg x y) =+ ModuleInstanceNamedArg (noPos x) (noPos y)+ instance NoPos (NestedModule name) where noPos (NestedModule m) = NestedModule (noPos m) @@ -1014,13 +1382,43 @@ DPrimType t -> DPrimType (noPos t) TDNewtype n -> TDNewtype(noPos n) Include x -> Include (noPos x)+ DModule d -> DModule (noPos d)+ DImport d -> DImport (noPos d)+ DModParam d -> DModParam (noPos d)+ DParamDecl _ ds -> DParamDecl rng (noPos ds)+ where rng = Range { from = Position 0 0, to = Position 0 0, source = "" }+ DInterfaceConstraint d ds -> DInterfaceConstraint d (noPos (noPos <$> ds))++instance NoPos (ParamDecl name) where+ noPos pd =+ case pd of DParameterFun d -> DParameterFun (noPos d) DParameterType d -> DParameterType (noPos d)+ DParameterDecl d -> DParameterDecl (noPos d) DParameterConstraint d -> DParameterConstraint (noPos d)- DModule d -> DModule (noPos d)- DImport d -> DImport (noPos d) +instance NoPos (Signature name) where+ noPos sig = Signature { sigImports = sigImports sig+ , sigTypeParams = map noPos (sigTypeParams sig)+ , sigDecls = map noPos (sigDecls sig)+ , sigConstraints = map noPos (sigConstraints sig)+ , sigFunParams = map noPos (sigFunParams sig)+ } +instance NoPos (SigDecl name) where+ noPos decl =+ case decl of+ SigTySyn ts mb -> SigTySyn (noPos ts) mb+ SigPropSyn ps mb -> SigPropSyn (noPos ps) mb++instance NoPos (ModParam name) where+ noPos mp = ModParam { mpSignature = noPos (mpSignature mp)+ , mpAs = mpAs mp+ , mpName = mpName mp+ , mpDoc = noPos <$> mpDoc mp+ , mpRenaming = mpRenaming mp+ }+ instance NoPos (PrimType name) where noPos x = x @@ -1047,9 +1445,10 @@ DLocated x _ -> noPos x instance NoPos (Newtype name) where- noPos n = Newtype { nName = noPos (nName n)- , nParams = nParams n- , nBody = fmap noPos (nBody n)+ noPos n = Newtype { nName = noPos (nName n)+ , nParams = nParams n+ , nConName = nConName n+ , nBody = fmap noPos (nBody n) } instance NoPos (Bind name) where@@ -1082,8 +1481,6 @@ case expr of EVar x -> EVar x ELit x -> ELit x- ENeg x -> ENeg (noPos x)- EComplement x -> EComplement (noPos x) EGenerate x -> EGenerate (noPos x) ETuple x -> ETuple (noPos x) ERecord x -> ERecord (fmap noPos x)@@ -1110,6 +1507,7 @@ ESplit x -> ESplit (noPos x) EParens e -> EParens (noPos e) EInfix x y f z -> EInfix (noPos x) y f (noPos z)+ EPrefix op x -> EPrefix op (noPos x) instance NoPos (UpdField name) where noPos (UpdField h xs e) = UpdField h xs (noPos e)@@ -1154,7 +1552,7 @@ TNum n -> TNum n TChar n -> TChar n TLocated x _ -> noPos x- TParens x -> TParens (noPos x)+ TParens x k -> TParens (noPos x) k TInfix x y f z-> TInfix (noPos x) y f (noPos z) instance NoPos (Prop name) where
+ src/Cryptol/Parser/ExpandPropGuards.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}++-- |+-- Module : Cryptol.Parser.PropGuards+-- Copyright : (c) 2022 Galois, Inc.+-- License : BSD3+-- Maintainer : cryptol@galois.com+-- Stability : provisional+-- Portability : portable+--+-- Expands PropGuards into a top-level definition for each case, and rewrites+-- the body of each case to be an appropriate call to the respectively generated+-- function.+module Cryptol.Parser.ExpandPropGuards where++import Control.DeepSeq+import Cryptol.Parser.AST+import Cryptol.Utils.PP+import Cryptol.Utils.Panic (panic)+import Data.Text (pack)+import GHC.Generics (Generic)++-- | Monad+type ExpandPropGuardsM a = Either Error a++runExpandPropGuardsM :: ExpandPropGuardsM a -> Either Error a+runExpandPropGuardsM m = m++-- | Error+data Error = NoSignature (Located PName)+ deriving (Show, Generic, NFData)++instance PP Error where+ ppPrec _ err = case err of+ NoSignature x ->+ text "At" <+> pp (srcRange x) <.> colon+ <+> text "Declarations using constraint guards require an explicit type signature."++expandPropGuards :: ModuleG mname PName -> ExpandPropGuardsM (ModuleG mname PName)+expandPropGuards m =+ do def <- expandModuleDef (mDef m)+ pure m { mDef = def }++expandModuleDef :: ModuleDefinition PName -> ExpandPropGuardsM (ModuleDefinition PName)+expandModuleDef m =+ case m of+ NormalModule ds -> NormalModule . concat <$> mapM expandTopDecl ds+ FunctorInstance {} -> pure m+ InterfaceModule {} -> pure m++expandTopDecl :: TopDecl PName -> ExpandPropGuardsM [TopDecl PName]+expandTopDecl topDecl =+ case topDecl of+ Decl topLevelDecl ->+ do ds <- expandDecl (tlValue topLevelDecl)+ pure [ Decl topLevelDecl { tlValue = d } | d <- ds ]++ DModule tl | NestedModule m <- tlValue tl ->+ do m1 <- expandPropGuards m+ pure [DModule tl { tlValue = NestedModule m1 }]++ _ -> pure [topDecl]++expandDecl :: Decl PName -> ExpandPropGuardsM [Decl PName]+expandDecl decl =+ case decl of+ DBind bind -> do bs <- expandBind bind+ pure (map DBind bs)+ _ -> pure [decl]++expandBind :: Bind PName -> ExpandPropGuardsM [Bind PName]+expandBind bind =+ case thing (bDef bind) of+ DPropGuards guards -> do+ Forall params props t rng <-+ case bSignature bind of+ Just schema -> pure schema+ Nothing -> Left . NoSignature $ bName bind+ let goGuard ::+ PropGuardCase PName ->+ ExpandPropGuardsM (PropGuardCase PName, Bind PName)+ goGuard (PropGuardCase props' e) = do+ bName' <- newName (bName bind) (thing <$> props')+ -- call to generated function+ tParams <- case bSignature bind of+ Just (Forall tps _ _ _) -> pure tps+ Nothing -> Left $ NoSignature (bName bind)+ typeInsts <-+ (\(TParam n _ _) -> Right . PosInst $ TUser n [])+ `traverse` tParams+ let e' = foldl EApp (EAppT (EVar $ thing bName') typeInsts) (patternToExpr <$> bParams bind)+ pure+ ( PropGuardCase props' e',+ bind+ { bName = bName',+ -- include guarded props in signature+ bSignature = Just (Forall params+ (props <> map thing props')+ t rng),+ -- keeps same location at original bind+ -- i.e. "on top of" original bind+ bDef = (bDef bind) {thing = DExpr e}+ }+ )+ (guards', binds') <- unzip <$> mapM goGuard guards+ pure $+ bind {bDef = DPropGuards guards' <$ bDef bind} :+ binds'+ _ -> pure [bind]++patternToExpr :: Pattern PName -> Expr PName+patternToExpr (PVar locName) = EVar (thing locName)+patternToExpr _ =+ panic "patternToExpr"+ ["Unimplemented: patternToExpr of anything other than PVar"]++newName :: Located PName -> [Prop PName] -> ExpandPropGuardsM (Located PName)+newName locName props =+ pure case thing locName of+ Qual modName ident ->+ let txt = identText ident+ txt' = pack $ show $ pp props+ in Qual modName (mkIdent $ txt <> txt') <$ locName+ UnQual ident ->+ let txt = identText ident+ txt' = pack $ show $ pp props+ in UnQual (mkIdent $ txt <> txt') <$ locName+ NewName _ _ ->+ panic "mkName"+ [ "During expanding prop guards"+ , "tried to make new name from NewName case of PName"+ ]
src/Cryptol/Parser/Layout.hs view
@@ -64,7 +64,11 @@ | let t = head ts0 rng = srcRange t blockCol = max 1 (col (from rng)) -- see startImplicitBlock- , isMod && tokenType (thing t) /= KW KW_module =+ implictMod = case map (tokenType . thing) ts0 of+ KW KW_module : _ -> False+ KW KW_interface : KW KW_module : _ -> False+ _ -> True+ , isMod && implictMod = virt rng VCurlyL : go [ Virtual blockCol ] blockCol True ts0 | otherwise =
src/Cryptol/Parser/Lexer.x view
@@ -98,12 +98,12 @@ -- Please update the docs, if you add new entries. "else" { emit $ KW KW_else }-"extern" { emit $ KW KW_extern } "if" { emit $ KW KW_if } "private" { emit $ KW KW_private } "include" { emit $ KW KW_include } "module" { emit $ KW KW_module } "submodule" { emit $ KW KW_submodule }+"interface" { emit $ KW KW_interface } "newtype" { emit $ KW KW_newtype } "pragma" { emit $ KW KW_pragma } "property" { emit $ KW KW_property }@@ -115,7 +115,6 @@ "import" { emit $ KW KW_import } "as" { emit $ KW KW_as } "hiding" { emit $ KW KW_hiding }-"newtype" { emit $ KW KW_newtype } "down" { emit $ KW KW_down } "by" { emit $ KW KW_by } @@ -126,6 +125,7 @@ "primitive" { emit $ KW KW_primitive } "parameter" { emit $ KW KW_parameter } "constraint" { emit $ KW KW_constraint }+"foreign" { emit $ KW KW_foreign } "Prop" { emit $ KW KW_Prop }
src/Cryptol/Parser/Name.hs view
@@ -7,6 +7,7 @@ -- Portability : portable {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE Safe #-} module Cryptol.Parser.Name where @@ -33,6 +34,7 @@ -- | Passes that can generate fresh names. data Pass = NoPat | MonoValues+ | ExpandPropGuards String deriving (Eq,Ord,Show,Generic) instance NFData PName@@ -54,8 +56,9 @@ getIdent (NewName p i) = packIdent ("__" ++ pass ++ show i) where pass = case p of- NoPat -> "p"- MonoValues -> "mv"+ NoPat -> "p"+ MonoValues -> "mv"+ ExpandPropGuards _ -> "epg" isGeneratedName :: PName -> Bool isGeneratedName x =
src/Cryptol/Parser/Names.hs view
@@ -9,6 +9,8 @@ -- This module defines the scoping rules for value- and type-level -- names in Cryptol. +{-# LANGUAGE Safe #-}+ module Cryptol.Parser.Names ( tnamesNT , tnamesT@@ -18,6 +20,7 @@ , tnamesD , namesB , namesP+ , namesNT , boundNames , boundNamesSet@@ -33,6 +36,9 @@ tnamesNT :: Newtype name -> ([Located name], ()) tnamesNT x = ([ nName x ], ()) +namesNT :: Newtype name -> ([Located name], ())+namesNT x = ([ (nName x) { thing = nConName x } ], ())+ -- | The names defined and used by a group of mutually recursive declarations. namesDs :: Ord name => [Decl name] -> ([Located name], Set name) namesDs ds = (defs, boundLNames defs (Set.unions frees))@@ -63,7 +69,9 @@ namesDef :: Ord name => BindDef name -> Set name namesDef DPrim = Set.empty+namesDef DForeign = Set.empty namesDef (DExpr e) = namesE e+namesDef (DPropGuards guards) = Set.unions (map (namesE . pgcExpr) guards) -- | The names used by an expression.@@ -72,8 +80,6 @@ case expr of EVar x -> Set.singleton x ELit _ -> Set.empty- ENeg e -> namesE e- EComplement e -> namesE e EGenerate e -> namesE e ETuple es -> Set.unions (map namesE es) ERecord fs -> Set.unions (map (namesE . snd) (recordElements fs))@@ -102,6 +108,7 @@ ESplit e -> namesE e EParens e -> namesE e EInfix a o _ b-> Set.insert (thing o) (Set.union (namesE a) (namesE b))+ EPrefix _ e -> namesE e namesUF :: Ord name => UpdField name -> Set name namesUF (UpdField _ _ e) = namesE e@@ -184,16 +191,20 @@ tnamesDef :: Ord name => BindDef name -> Set name tnamesDef DPrim = Set.empty+tnamesDef DForeign = Set.empty tnamesDef (DExpr e) = tnamesE e+tnamesDef (DPropGuards guards) = Set.unions (map tnamesPropGuardCase guards) +tnamesPropGuardCase :: Ord name => PropGuardCase name -> Set name+tnamesPropGuardCase c =+ Set.unions (tnamesE (pgcExpr c) : map (tnamesC . thing) (pgcProps c))+ -- | The type names used by an expression. tnamesE :: Ord name => Expr name -> Set name tnamesE expr = case expr of EVar _ -> Set.empty ELit _ -> Set.empty- ENeg e -> tnamesE e- EComplement e -> tnamesE e EGenerate e -> tnamesE e ETuple es -> Set.unions (map tnamesE es) ERecord fs -> Set.unions (map (tnamesE . snd) (recordElements fs))@@ -224,6 +235,7 @@ ESplit e -> tnamesE e EParens e -> tnamesE e EInfix a _ _ b -> Set.union (tnamesE a) (tnamesE b)+ EPrefix _ e -> tnamesE e tnamesUF :: Ord name => UpdField name -> Set name tnamesUF (UpdField _ _ e) = tnamesE e@@ -277,6 +289,6 @@ TTyApp fs -> Set.unions (map (tnamesT . value) fs) TLocated t _ -> tnamesT t TUser x ts -> Set.insert x (Set.unions (map tnamesT ts))- TParens t -> tnamesT t+ TParens t _ -> tnamesT t TInfix a x _ c-> Set.insert (thing x) (Set.union (tnamesT a) (tnamesT c))
src/Cryptol/Parser/NoInclude.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE BlockArguments #-} module Cryptol.Parser.NoInclude ( removeIncludesModule , IncludeError(..), ppIncludeError@@ -19,6 +20,8 @@ import qualified Control.Exception as X import qualified Control.Monad.Fail as Fail +import Data.Set(Set)+import qualified Data.Set as Set import Data.ByteString (ByteString) import Data.Either (partitionEithers) import Data.Text(Text)@@ -29,19 +32,20 @@ import System.Directory (makeAbsolute) import System.FilePath (takeDirectory,(</>),isAbsolute) +import Cryptol.Utils.PP hiding ((</>)) import Cryptol.Parser (parseProgramWith) import Cryptol.Parser.AST import Cryptol.Parser.LexerUtils (Config(..),defaultConfig) import Cryptol.Parser.ParserUtils import Cryptol.Parser.Unlit (guessPreProc)-import Cryptol.Utils.PP hiding ((</>)) removeIncludesModule :: (FilePath -> IO ByteString) -> FilePath -> Module PName ->- IO (Either [IncludeError] (Module PName))-removeIncludesModule reader modPath m = runNoIncM reader modPath (noIncludeModule m)+ IO (Either [IncludeError] (Module PName, Set FilePath))+removeIncludesModule reader modPath m =+ runNoIncM reader modPath (noIncludeModule m) data IncludeError = IncludeFailed (Located FilePath)@@ -72,20 +76,40 @@ newtype NoIncM a = M- { unM :: ReaderT Env (ExceptionT [IncludeError] IO) a }+ { unM :: ReaderT Env+ ( ExceptionT [IncludeError]+ ( StateT Deps+ IO+ )) a } +type Deps = Set FilePath+ data Env = Env { envSeen :: [Located FilePath] -- ^ Files that have been loaded+ , envIncPath :: FilePath -- ^ The path that includes are relative to+ , envFileReader :: FilePath -> IO ByteString -- ^ How to load files } -runNoIncM :: (FilePath -> IO ByteString) -> FilePath -> NoIncM a -> IO (Either [IncludeError] a)++runNoIncM ::+ (FilePath -> IO ByteString) ->+ FilePath ->+ NoIncM a -> IO (Either [IncludeError] (a,Deps)) runNoIncM reader sourcePath m = do incPath <- getIncPath sourcePath- runM (unM m) Env { envSeen = [], envIncPath = incPath, envFileReader = reader }+ (mb,s) <- runM (unM m)+ Env { envSeen = []+ , envIncPath = incPath+ , envFileReader = reader+ }+ Set.empty+ pure+ do ok <- mb+ pure (ok,s) tryNoIncM :: NoIncM a -> NoIncM (Either [IncludeError] a) tryNoIncM m = M (try (unM m))@@ -107,11 +131,17 @@ fromIncPath :: FilePath -> NoIncM FilePath fromIncPath path | isAbsolute path = return path- | otherwise = M $+ | otherwise = M do Env { .. } <- ask return (envIncPath </> path) +addDep :: FilePath -> NoIncM ()+addDep path = M+ do s <- get+ let s1 = Set.insert path s+ s1 `seq` set s1 + instance Functor NoIncM where fmap = liftM @@ -161,9 +191,14 @@ -- | Remove includes from a module. noIncludeModule :: ModuleG mname PName -> NoIncM (ModuleG mname PName)-noIncludeModule m = update `fmap` collectErrors noIncTopDecl (mDecls m)+noIncludeModule m =+ do newDef <- case mDef m of+ NormalModule ds -> NormalModule <$> doDecls ds+ FunctorInstance f as is -> pure (FunctorInstance f as is)+ InterfaceModule s -> pure (InterfaceModule s)+ pure m { mDef = newDef } where- update tds = m { mDecls = concat tds }+ doDecls = fmap concat . collectErrors noIncTopDecl -- | Remove includes from a program. noIncludeProgram :: Program PName -> NoIncM (Program PName)@@ -177,9 +212,8 @@ Decl _ -> pure [td] DPrimType {} -> pure [td] TDNewtype _-> pure [td]- DParameterType {} -> pure [td]- DParameterConstraint {} -> pure [td]- DParameterFun {} -> pure [td]+ DParamDecl {} -> pure [td]+ DInterfaceConstraint {} -> pure [td] Include lf -> resolveInclude lf DModule tl -> case tlValue tl of@@ -187,13 +221,17 @@ do m1 <- noIncludeModule m pure [ DModule tl { tlValue = NestedModule m1 } ] DImport {} -> pure [td]+ DModParam {} -> pure [td] -- | Resolve the file referenced by a include into a list of top-level -- declarations. resolveInclude :: Located FilePath -> NoIncM [TopDecl PName] resolveInclude lf = pushPath lf $ do source <- readInclude lf- case parseProgramWith (defaultConfig { cfgSource = thing lf, cfgPreProc = guessPreProc (thing lf) }) source of+ let cfg = defaultConfig { cfgSource = thing lf+ , cfgPreProc = guessPreProc (thing lf)+ }+ case parseProgramWith cfg source of Right prog -> do Program ds <-@@ -206,8 +244,9 @@ -- | Read a file referenced by an include. readInclude :: Located FilePath -> NoIncM Text readInclude path = do- readBytes <- envFileReader <$> M ask+ readBytes <- envFileReader <$> M ask file <- fromIncPath (thing path)+ addDep file sourceBytes <- readBytes file `failsWith` handler sourceText <- X.evaluate (T.decodeUtf8' sourceBytes) `failsWith` handler case sourceText of
src/Cryptol/Parser/NoPat.hs view
@@ -8,8 +8,8 @@ -- -- The purpose of this module is to convert all patterns to variable -- patterns. It also eliminates pattern bindings by de-sugaring them--- into `Bind`. Furthermore, here we associate signatures and pragmas--- with the names to which they belong.+-- into `Bind`. Furthermore, here we associate signatures, fixities,+-- and pragmas with the names to which they belong. {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}@@ -17,6 +17,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE BlockArguments #-} module Cryptol.Parser.NoPat (RemovePatterns(..),Error(..)) where import Cryptol.Parser.AST@@ -150,8 +151,6 @@ case expr of EVar {} -> return expr ELit {} -> return expr- ENeg e -> ENeg <$> noPatE e- EComplement e -> EComplement <$> noPatE e EGenerate e -> EGenerate <$> noPatE e ETuple es -> ETuple <$> mapM noPatE es ERecord es -> ERecord <$> traverse (traverse noPatE) es@@ -176,6 +175,7 @@ ESplit e -> ESplit <$> noPatE e EParens e -> EParens <$> noPatE e EInfix x y f z-> EInfix <$> noPatE x <*> pure y <*> pure f <*> noPatE z+ EPrefix op e -> EPrefix op <$> noPatE e noPatUF :: UpdField PName -> NoPatM (UpdField PName)@@ -220,10 +220,29 @@ | otherwise -> panic "NoPat" [ "noMatchB: primitive with params" , show b ] + DForeign+ | null (bParams b) -> return b+ | otherwise -> panic "NoPat" [ "noMatchB: foreign with params"+ , show b ]+ DExpr e -> do e' <- noPatFun (Just (thing (bName b))) 0 (bParams b) e return b { bParams = [], bDef = DExpr e' <$ bDef b } + DPropGuards guards ->+ do let nm = thing (bName b)+ ps = bParams b+ gs <- mapM (noPatPropGuardCase nm ps) guards+ pure b { bParams = [], bDef = DPropGuards gs <$ bDef b }++noPatPropGuardCase ::+ PName ->+ [Pattern PName] ->+ PropGuardCase PName -> NoPatM (PropGuardCase PName)+noPatPropGuardCase f xs pc =+ do e <- noPatFun (Just f) 0 xs (pgcExpr pc)+ pure pc { pgcExpr = e }+ noMatchD :: Decl PName -> NoPatM [Decl PName] noMatchD decl = case decl of@@ -334,8 +353,12 @@ noPatModule :: ModuleG mname PName -> NoPatM (ModuleG mname PName) noPatModule m =- do ds1 <- noPatTopDs (mDecls m)- return m { mDecls = ds1 }+ do def <-+ case mDef m of+ NormalModule ds -> NormalModule <$> noPatTopDs ds+ FunctorInstance f as i -> pure (FunctorInstance f as i)+ InterfaceModule s -> pure (InterfaceModule s)+ pure m { mDef = def } -------------------------------------------------------------------------------- @@ -372,23 +395,8 @@ let d1 = DPrimType tl { tlValue = pt } (d1 :) <$> annotTopDs ds - DParameterType p ->- do p1 <- annotParameterType p- (DParameterType p1 :) <$> annotTopDs ds-- DParameterConstraint {} -> (d :) <$> annotTopDs ds-- DParameterFun p ->- do AnnotMap { .. } <- get- let rm _ _ = Nothing- name = thing (pfName p)- case Map.updateLookupWithKey rm name annValueFs of- (Nothing,_) -> (d :) <$> annotTopDs ds- (Just f,fs1) ->- do mbF <- lift (checkFixs name f)- set AnnotMap { annValueFs = fs1, .. }- let p1 = p { pfFixity = mbF }- (DParameterFun p1 :) <$> annotTopDs ds+ DParamDecl {} -> (d :) <$> annotTopDs ds+ DInterfaceConstraint {} -> (d :) <$> annotTopDs ds -- XXX: we may want to add pragmas to newtypes? TDNewtype {} -> (d :) <$> annotTopDs ds@@ -401,6 +409,8 @@ DImport {} -> (d :) <$> annotTopDs ds + DModParam {} -> (d :) <$> annotTopDs ds+ [] -> return [] @@ -482,15 +492,6 @@ annotPrimType pt = do f <- annotTyThing (thing (primTName pt)) pure pt { primTFixity = f }---- | Annotate a module's type parameter.-annotParameterType :: Annotates (ParameterType PName)-annotParameterType pt =- do f <- annotTyThing (thing (ptName pt))- pure pt { ptFixity = f }--- -- | Check for multiple signatures. checkSigs :: PName -> [Located (Schema PName)] -> NoPatM (Maybe (Schema PName))
src/Cryptol/Parser/ParserUtils.hs view
@@ -12,16 +12,21 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE PatternGuards #-}+{-# LANGUAGE BlockArguments #-} {-# LANGUAGE OverloadedStrings #-} -- See Note [-Wincomplete-uni-patterns and irrefutable patterns] in Cryptol.TypeCheck.TypePat {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Cryptol.Parser.ParserUtils where +import qualified Data.Text as Text+import Data.Char(isAlphaNum) import Data.Maybe(fromMaybe) import Data.Bits(testBit,setBit)+import Data.Maybe(mapMaybe)+import Data.List(foldl') import Data.List.NonEmpty ( NonEmpty(..) ) import qualified Data.List.NonEmpty as NE-import Control.Monad(liftM,ap,unless,guard)+import Control.Monad(liftM,ap,unless,guard,msum) import qualified Control.Monad.Fail as Fail import Data.Text(Text) import qualified Data.Text as T@@ -40,7 +45,13 @@ import Cryptol.Parser.Token(SelectorType(..)) import Cryptol.Parser.Position import Cryptol.Parser.Utils (translateExprToNumT,widthIdent)-import Cryptol.Utils.Ident(packModName,packIdent,modNameChunks)+import Cryptol.Utils.Ident( packModName,packIdent,modNameChunks+ , identAnonArg, identAnonIfaceMod+ , modNameArg, modNameIfaceMod+ , modNameToText, modNameIsNormal+ , modNameToNormalModName+ , unpackIdent+ ) import Cryptol.Utils.PP import Cryptol.Utils.Panic import Cryptol.Utils.RecordMap@@ -193,6 +204,27 @@ mkModName :: [Text] -> ModName mkModName = packModName +-- | This is how we derive the name of a module parameter from the+-- @import source@ declaration.+mkModParamName :: Located (ImpName PName) -> Maybe (Located ModName) -> Ident+mkModParamName lsig qual =+ case qual of+ Nothing ->+ case thing lsig of+ ImpTop t+ | modNameIsNormal t -> packIdent (last (modNameChunks t))+ | otherwise -> identAnonIfaceMod+ $ packIdent+ $ last+ $ modNameChunks+ $ modNameToNormalModName t+ ImpNested nm ->+ case nm of+ UnQual i -> i+ Qual _ i -> i+ NewName {} -> panic "mkModParamName" ["Unexpected NewName",show lsig]+ Just m -> packIdent (last (modNameChunks (thing m)))+ -- Note that type variables are not resolved at this point: they are tcons. mkSchema :: [TParam PName] -> [Prop PName] -> Type PName -> Schema PName mkSchema xs ps t = Forall xs ps t Nothing@@ -272,7 +304,9 @@ TWild -> bad "Wildcard types" TUser {} -> ok - TParens t -> validDemotedType rng t+ TParens t mb -> case mb of+ Nothing -> validDemotedType rng t+ Just _ -> bad "kind annotation" TInfix{} -> ok where bad x = errorMessage rng [x ++ " cannot be demoted."]@@ -486,7 +520,7 @@ mkParFun :: Maybe (Located Text) -> Located PName -> Schema PName ->- TopDecl PName+ ParamDecl PName mkParFun mbDoc n s = DParameterFun ParameterFun { pfName = n , pfSchema = s , pfDoc = thing <$> mbDoc@@ -496,7 +530,7 @@ mkParType :: Maybe (Located Text) -> Located PName -> Located Kind ->- ParseM (TopDecl PName)+ ParseM (ParamDecl PName) mkParType mbDoc n k = do num <- P $ \_ _ s -> let nu = sNextTyParamNum s in Right (nu, s { sNextTyParamNum = nu + 1 })@@ -511,16 +545,17 @@ changeExport :: ExportType -> [TopDecl PName] -> [TopDecl PName] changeExport e = map change where- change (Decl d) = Decl d { tlExport = e }- change (DPrimType t) = DPrimType t { tlExport = e }- change (TDNewtype n) = TDNewtype n { tlExport = e }- change (DModule m) = DModule m { tlExport = e }- change td@Include{} = td- change td@DImport{} = td- change (DParameterType {}) = panic "changeExport" ["private type parameter?"]- change (DParameterFun {}) = panic "changeExport" ["private value parameter?"]- change (DParameterConstraint {}) =- panic "changeExport" ["private type constraint parameter?"]+ change decl =+ case decl of+ Decl d -> Decl d { tlExport = e }+ DPrimType t -> DPrimType t { tlExport = e }+ TDNewtype n -> TDNewtype n { tlExport = e }+ DModule m -> DModule m { tlExport = e }+ DModParam {} -> decl+ Include{} -> decl+ DImport{} -> decl+ DParamDecl{} -> decl+ DInterfaceConstraint {} -> decl mkTypeInst :: Named (Type PName) -> TypeInst PName mkTypeInst x | nullIdent (thing (name x)) = PosInst (value x)@@ -532,22 +567,99 @@ | n == widthIdent = errorMessage rng ["`width` is not a valid type parameter name."] | otherwise = return (TParam (mkUnqual n) k (Just rng)) -mkTySyn :: Located PName -> [TParam PName] -> Type PName -> ParseM (Decl PName)-mkTySyn ln ps b- | getIdent (thing ln) == widthIdent =- errorMessage (srcRange ln) ["`width` is not a valid type synonym name."] - | otherwise =- return $ DType $ TySyn ln Nothing ps b+mkTySyn :: Type PName -> Type PName -> ParseM (Decl PName)+mkTySyn thead tdef =+ do (nm,params) <- typeToDecl thead+ pure (DType (TySyn nm Nothing params tdef)) -mkPropSyn :: Located PName -> [TParam PName] -> Type PName -> ParseM (Decl PName)-mkPropSyn ln ps b- | getIdent (thing ln) == widthIdent =- errorMessage (srcRange ln) ["`width` is not a valid constraint synonym name."]+mkPropSyn :: Type PName -> Type PName -> ParseM (Decl PName)+mkPropSyn thead tdef =+ do (nm,params) <- typeToDecl thead+ ps <- thing <$> mkProp tdef+ pure (DProp (PropSyn nm Nothing params ps)) - | otherwise =- DProp . PropSyn ln Nothing ps . thing <$> mkProp b+mkNewtype ::+ Type PName ->+ Located (RecordMap Ident (Range, Type PName)) ->+ ParseM (Newtype PName)+mkNewtype thead def =+ do (nm,params) <- typeToDecl thead+ pure (Newtype nm params (thing nm) (thing def)) +typeToDecl :: Type PName -> ParseM (Located PName, [TParam PName])+typeToDecl ty0 =+ case ty0 of+ TLocated ty loc -> goD loc ty+ _ -> panic "typeToDecl" ["Type location is missing."]++ where+ bad loc = errorMessage loc ["Invalid type declaration"]+ badP loc = errorMessage loc ["Invalid declaration parameter"]+++ goN loc n =+ case n of+ UnQual {} -> pure ()+ _ -> errorMessage loc ["Invalid declaration name"]++ goP loc ty =+ case ty of+ TLocated ty1 loc1 -> goP loc1 ty1++ TUser f [] ->+ do goN loc f+ pure TParam { tpName = f, tpKind = Nothing, tpRange = Just loc }++ TParens t mb ->+ case mb of+ Nothing -> badP loc+ Just k ->+ do p <- goP loc t+ case tpKind p of+ Nothing -> pure p { tpKind = Just k }+ Just {} -> badP loc++ TInfix {} -> badP loc+ TUser {} -> badP loc+ TFun {} -> badP loc+ TSeq {} -> badP loc+ TBit {} -> badP loc+ TNum {} -> badP loc+ TChar {} -> badP loc+ TRecord {} -> badP loc+ TWild {} -> badP loc+ TTyApp {} -> badP loc+ TTuple {} -> badP loc+++ goD loc ty =+ case ty of++ TLocated ty1 loc1 -> goD loc1 ty1++ TUser f ts ->+ do goN loc f+ ps <- mapM (goP loc) ts+ pure (Located { thing = f, srcRange = loc },ps)++ TInfix l f _ r ->+ do goN (srcRange f) (thing f)+ a <- goP loc l+ b <- goP loc r+ pure (f,[a,b])++ TFun {} -> bad loc+ TSeq {} -> bad loc+ TBit {} -> bad loc+ TNum {} -> bad loc+ TChar {} -> bad loc+ TRecord {} -> bad loc+ TWild {} -> bad loc+ TTyApp {} -> bad loc+ TTuple {} -> bad loc+ TParens {} -> bad loc+ polyTerm :: Range -> Integer -> Integer -> ParseM (Bool, Integer) polyTerm rng k p | k == 0 = return (False, p)@@ -610,6 +722,35 @@ rhs = mkGenerate (reverse ixs) e -- NOTE: The lists of patterns are reversed!+mkPropGuardsDecl ::+ LPName ->+ ([Pattern PName], [Pattern PName]) ->+ [PropGuardCase PName] ->+ ParseM (Decl PName)+mkPropGuardsDecl f (ps, ixs) guards =+ do unless (null ixs) $+ errorMessage (srcRange f)+ ["Indexed sequence definitions may not use constraint guards"]+ let gs = reverse guards+ pure $+ DBind Bind { bName = f+ , bParams = reverse ps+ , bDef = Located (srcRange f) (DPropGuards gs)+ , bSignature = Nothing+ , bPragmas = []+ , bMono = False+ , bInfix = False+ , bFixity = Nothing+ , bDoc = Nothing+ , bExport = Public+ }++mkConstantPropGuardsDecl ::+ LPName -> [PropGuardCase PName] -> ParseM (Decl PName)+mkConstantPropGuardsDecl f guards =+ mkPropGuardsDecl f ([],[]) guards++-- NOTE: The lists of patterns are reversed! mkIndexedExpr :: ([Pattern PName], [Pattern PName]) -> Expr PName -> Expr PName mkIndexedExpr (ps, ixs) body | null ps = mkGenerate (reverse ixs) body@@ -624,19 +765,36 @@ where addIfThen (cond, doexpr) elseExpr = EIf cond doexpr elseExpr --- | Generate a signature and a primitive binding. The reason for generating--- both instead of just adding the signature at this point is that it means the--- primitive declarations don't need to be treated differently in the noPat+mkPrimDecl :: Maybe (Located Text) -> LPName -> Schema PName -> [TopDecl PName]+mkPrimDecl = mkNoImplDecl DPrim++mkForeignDecl ::+ Maybe (Located Text) -> LPName -> Schema PName -> ParseM [TopDecl PName]+mkForeignDecl mbDoc nm ty =+ do let txt = unpackIdent (getIdent (thing nm))+ unless (all isOk txt)+ (errorMessage (srcRange nm)+ [ "`" ++ txt ++ "` is not a valid foreign name."+ , "The name should contain only alpha-numeric characters or '_'."+ ])+ pure (mkNoImplDecl DForeign mbDoc nm ty)+ where+ isOk c = c == '_' || isAlphaNum c++-- | Generate a signature and a binding for value declarations with no+-- implementation (i.e. primitive or foreign declarations). The reason for+-- generating both instead of just adding the signature at this point is that it+-- means the declarations don't need to be treated differently in the noPat -- pass. This is also the reason we add the doc to the TopLevel constructor, -- instead of just place it on the binding directly. A better solution might be--- to just have a different constructor for primitives.-mkPrimDecl ::- Maybe (Located Text) -> LPName -> Schema PName -> [TopDecl PName]-mkPrimDecl mbDoc ln sig =+-- to just have a different constructor for primitives and foreigns.+mkNoImplDecl :: BindDef PName+ -> Maybe (Located Text) -> LPName -> Schema PName -> [TopDecl PName]+mkNoImplDecl def mbDoc ln sig = [ exportDecl mbDoc Public $ DBind Bind { bName = ln , bParams = []- , bDef = at sig (Located emptyRange DPrim)+ , bDef = at sig (Located emptyRange def) , bSignature = Nothing , bPragmas = [] , bMono = False@@ -761,6 +919,10 @@ distrLoc x = [ Located { srcRange = r, thing = a } | a <- thing x ] where r = srcRange x +mkPropGuards :: Type PName -> ParseM [Located (Prop PName)]+mkPropGuards ty =+ do lp <- mkProp ty+ pure [ lp { thing = p } | p <- thing lp ] mkProp :: Type PName -> ParseM (Located [Prop PName]) mkProp ty =@@ -777,7 +939,10 @@ TInfix{} -> return [CType t] TUser{} -> return [CType t] TTuple ts -> concat `fmap` mapM (props r) ts- TParens t' -> props r t'+ TParens t' mb -> case mb of+ Nothing -> props r t'+ Just _ -> err+ TLocated t' r' -> props r' t' TFun{} -> err@@ -795,8 +960,7 @@ -- | Make an ordinary module mkModule :: Located ModName -> [TopDecl PName] -> Module PName mkModule nm ds = Module { mName = nm- , mInstance = Nothing- , mDecls = ds+ , mDef = NormalModule ds } mkNested :: Module PName -> ParseM (NestedModule PName)@@ -809,23 +973,103 @@ nm = mName m r = srcRange nm +mkSigDecl :: Maybe (Located Text) -> (Located PName,Signature PName) -> TopDecl PName+mkSigDecl doc (nm,sig) =+ DModule+ TopLevel { tlExport = Public+ , tlDoc = doc+ , tlValue = NestedModule+ Module { mName = nm+ , mDef = InterfaceModule sig+ }+ }++mkInterfaceConstraint ::+ Maybe (Located Text) -> Type PName -> ParseM [TopDecl PName]+mkInterfaceConstraint mbDoc ty =+ do ps <- mkProp ty+ pure [DInterfaceConstraint (thing <$> mbDoc) ps]++mkParDecls :: [ParamDecl PName] -> TopDecl PName+mkParDecls ds = DParamDecl loc (mkInterface' [] ds)+ where loc = rCombs (mapMaybe getLoc ds)++onlySimpleImports :: [Located (ImportG (ImpName PName))] -> ParseM ()+onlySimpleImports = mapM_ check+ where+ check i =+ case iInst (thing i) of+ Nothing -> pure ()+ Just _ ->+ errorMessage (srcRange i)+ [ "Functor instantiations are not supported in this context."+ , "The imported entity needs to be just the name of a module."+ , "A workaround would be to do the instantion in the outer context."+ ]++mkInterface' :: [Located (ImportG (ImpName PName))] ->+ [ParamDecl PName] -> Signature PName+mkInterface' is =+ foldl' add+ Signature { sigImports = is+ , sigTypeParams = []+ , sigDecls = []+ , sigConstraints = []+ , sigFunParams = []+ }+ where+ add s d =+ case d of+ DParameterType pt -> s { sigTypeParams = pt : sigTypeParams s }+ DParameterConstraint ps -> s { sigConstraints = ps ++ sigConstraints s }+ DParameterDecl pd -> s { sigDecls = pd : sigDecls s }+ DParameterFun pf -> s { sigFunParams = pf : sigFunParams s }++++mkInterface :: [Located (ImportG (ImpName PName))] ->+ [ParamDecl PName] -> ParseM (Signature PName)+mkInterface is ps =+ do onlySimpleImports is+ pure (mkInterface' is ps)++mkIfacePropSyn :: Maybe Text -> Decl PName -> ParamDecl PName+mkIfacePropSyn mbDoc d =+ case d of+ DLocated d1 _ -> mkIfacePropSyn mbDoc d1+ DType ts -> DParameterDecl (SigTySyn ts mbDoc)+ DProp ps -> DParameterDecl (SigPropSyn ps mbDoc)+ _ -> panic "mkIfacePropSyn" [ "Unexpected declaration", show (pp d) ]++ -- | Make an unnamed module---gets the name @Main@.-mkAnonymousModule :: [TopDecl PName] -> Module PName-mkAnonymousModule = mkModule Located { srcRange = emptyRange+mkAnonymousModule :: [TopDecl PName] -> ParseM [Module PName]+mkAnonymousModule = mkTopMods+ . mkModule Located { srcRange = emptyRange , thing = mkModName [T.pack "Main"] } -- | Make a module which defines a functor instance.-mkModuleInstance :: Located ModName ->- Located ModName ->- [TopDecl PName] ->- Module PName-mkModuleInstance nm fun ds =- Module { mName = nm- , mInstance = Just fun- , mDecls = ds+mkModuleInstanceAnon :: Located ModName ->+ Located (ImpName PName) ->+ [TopDecl PName] ->+ Module PName+mkModuleInstanceAnon nm fun ds =+ Module { mName = nm+ , mDef = FunctorInstance fun (DefaultInstAnonArg ds) mempty } +mkModuleInstance ::+ Located ModName ->+ Located (ImpName PName) ->+ ModuleInstanceArgs PName ->+ Module PName+mkModuleInstance m f as =+ Module { mName = m+ , mDef = FunctorInstance f as emptyModuleInstance+ }++ ufToNamed :: UpdField PName -> ParseM (Named (Expr PName)) ufToNamed (UpdField h ls e) = case (h,ls) of@@ -876,5 +1120,237 @@ case tokenType tok of Selector (TupleSelectorTok n) -> TupleSel n Nothing Selector (RecordSelectorTok t) -> RecordSel (mkIdent t) Nothing- _ -> panic "mkSelector"- [ "Unexpected selector token", show tok ]+ _ -> panic "mkSelector" [ "Unexpected selector token", show tok ]++mkBacktickImport ::+ Range ->+ Located (ImpName PName) ->+ Maybe (Located ModName) ->+ Maybe (Located ImportSpec) ->+ ParseM (Located (ImportG (ImpName PName)))+mkBacktickImport loc impName mbAs mbImportSpec =+ mkImport loc impName (Just inst) mbAs mbImportSpec Nothing+ where+ inst = DefaultInstArg (fmap (const AddParams) impName)+++mkImport ::+ Range ->+ Located (ImpName PName) ->+ Maybe (ModuleInstanceArgs PName) ->+ Maybe (Located ModName) ->+ Maybe (Located ImportSpec) ->+ Maybe (Located [Decl PName]) ->+ ParseM (Located (ImportG (ImpName PName)))++mkImport loc impName optInst mbAs mbImportSpec optImportWhere =+ do i <- getInst+ let end = fromMaybe (srcRange impName)+ $ msum [ srcRange <$> optImportWhere+ , srcRange <$> mbImportSpec+ , srcRange <$> mbAs+ ]++ pure Located { srcRange = rComb loc end+ , thing = Import+ { iModule = thing impName+ , iAs = thing <$> mbAs+ , iSpec = thing <$> mbImportSpec+ , iInst = i+ }+ }+ where+ getInst =+ case (optInst,optImportWhere) of+ (Just _, Just _) ->+ errorMessage loc [ "Invalid instantiating import."+ , "Import should have at most one of:"+ , " * { } instantiation, or"+ , " * where instantiation"+ ]+ (Just a, Nothing) -> pure (Just a)+ (Nothing, Just a) ->+ pure (Just (DefaultInstAnonArg (map instTop (thing a))))+ where+ instTop d = Decl TopLevel+ { tlExport = Public+ , tlDoc = Nothing+ , tlValue = d+ }+ (Nothing, Nothing) -> pure Nothing++++++mkTopMods :: Module PName -> ParseM [Module PName]+mkTopMods = desugarMod++mkTopSig :: Located ModName -> Signature PName -> [Module PName]+mkTopSig nm sig =+ [ Module { mName = nm+ , mDef = InterfaceModule sig+ }+ ]+++class MkAnon t where+ mkAnon :: AnonThing -> t -> t+ toImpName :: t -> ImpName PName++data AnonThing = AnonArg | AnonIfaceMod++instance MkAnon ModName where+ mkAnon what = case what of+ AnonArg -> modNameArg+ AnonIfaceMod -> modNameIfaceMod+ toImpName = ImpTop++instance MkAnon PName where+ mkAnon what = mkUnqual+ . case what of+ AnonArg -> identAnonArg+ AnonIfaceMod -> identAnonIfaceMod+ . getIdent+ toImpName = ImpNested+++desugarMod :: MkAnon name => ModuleG name PName -> ParseM [ModuleG name PName]+desugarMod mo =+ case mDef mo of++ FunctorInstance f as _ | DefaultInstAnonArg lds <- as ->+ do (ms,lds') <- desugarTopDs (mName mo) lds+ case ms of+ m : _ | InterfaceModule si <- mDef m+ , l : _ <- map (srcRange . ptName) (sigTypeParams si) +++ map (srcRange . pfName) (sigFunParams si) +++ [ srcRange (mName mo) ] ->+ errorMessage l+ [ "Instantiation of a parameterized module may not itself be "+ ++ "parameterized" ]+ _ -> pure ()+ let i = mkAnon AnonArg (thing (mName mo))+ nm = Located { srcRange = srcRange (mName mo), thing = i }+ as' = DefaultInstArg (ModuleArg . toImpName <$> nm)+ pure [ Module { mName = nm, mDef = NormalModule lds' }+ , mo { mDef = FunctorInstance f as' mempty }+ ]++ NormalModule ds ->+ do (newMs, newDs) <- desugarTopDs (mName mo) ds+ pure (newMs ++ [ mo { mDef = NormalModule newDs } ])++ _ -> pure [mo]+++desugarTopDs ::+ MkAnon name =>+ Located name ->+ [TopDecl PName] ->+ ParseM ([ModuleG name PName], [TopDecl PName])+desugarTopDs ownerName = go emptySig+ where+ isEmpty s =+ null (sigTypeParams s) && null (sigConstraints s) && null (sigFunParams s)++ emptySig = Signature+ { sigImports = []+ , sigTypeParams = []+ , sigDecls = []+ , sigConstraints = []+ , sigFunParams = []+ }++ jnSig s1 s2 = Signature { sigImports = j sigImports+ , sigTypeParams = j sigTypeParams+ , sigDecls = j sigDecls+ , sigConstraints = j sigConstraints+ , sigFunParams = j sigFunParams+ }++ where+ j f = f s1 ++ f s2++ addI i s = s { sigImports = i : sigImports s }++ go sig ds =+ case ds of++ []+ | isEmpty sig -> pure ([],[])+ | otherwise ->+ do let nm = mkAnon AnonIfaceMod <$> ownerName+ pure ( [ Module { mName = nm+ , mDef = InterfaceModule sig+ }+ ]+ , [ DModParam+ ModParam+ { mpSignature = toImpName <$> nm+ , mpAs = Nothing+ , mpName = mkModParamName (toImpName <$> nm)+ Nothing+ , mpDoc = Nothing+ , mpRenaming = mempty+ }+ ]+ )++ d : more ->+ let cont emit sig' =+ do (ms,ds') <- go sig' more+ pure (ms, emit ++ ds')+ in+ case d of++ DImport i | ImpTop _ <- iModule (thing i)+ , Nothing <- iInst (thing i) ->+ cont [d] (addI i sig)++ DImport i | Just inst <- iInst (thing i) ->+ do newDs <- desugarInstImport i inst+ cont newDs sig++ DParamDecl _ ds' -> cont [] (jnSig ds' sig)++ DModule tl | NestedModule mo <- tlValue tl ->+ do ms <- desugarMod mo+ cont [ DModule tl { tlValue = NestedModule m } | m <- ms ] sig++ _ -> cont [d] sig++desugarInstImport ::+ Located (ImportG (ImpName PName)) {- ^ The import -} ->+ ModuleInstanceArgs PName {- ^ The insantiation -} ->+ ParseM [TopDecl PName]+desugarInstImport i inst =+ do ms <- desugarMod+ Module { mName = i { thing = iname }+ , mDef = FunctorInstance+ (iModule <$> i) inst emptyModuleInstance+ }+ pure (DImport (newImp <$> i) : map modTop ms)++ where+ imp = thing i+ iname = mkUnqual+ $ mkIdent+ $ "import of " <> nm <> " at " <> Text.pack (show (pp (srcRange i)))+ where+ nm = case iModule imp of+ ImpTop f -> modNameToText f+ ImpNested n -> "submodule " <> Text.pack (show (pp n))++ newImp d = d { iModule = ImpNested iname+ , iInst = Nothing+ }++ modTop m = DModule TopLevel+ { tlExport = Private+ , tlDoc = Nothing+ , tlValue = NestedModule m+ }+++
src/Cryptol/Parser/Position.hs view
@@ -37,6 +37,11 @@ , source :: FilePath } deriving (Eq, Ord, Show, Generic, NFData) +-- | Returns `True` if the first range is contained in the second one.+rangeWithin :: Range -> Range -> Bool+a `rangeWithin` b =+ source a == source b && from a >= from b && to a <= to b+ -- | An empty range. -- -- Caution: using this on the LHS of a use of rComb will cause the empty source
src/Cryptol/Parser/Token.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE Safe #-} module Cryptol.Parser.Token where import Data.Text(Text)@@ -20,7 +21,6 @@ deriving (Eq, Show, Generic, NFData) data TokenKW = KW_else- | KW_extern | KW_fin | KW_if | KW_private@@ -50,6 +50,8 @@ | KW_primitive | KW_parameter | KW_constraint+ | KW_interface+ | KW_foreign | KW_Prop | KW_by | KW_down
src/Cryptol/Parser/Unlit.hs view
@@ -20,7 +20,7 @@ import Cryptol.Utils.Panic -data PreProc = None | Markdown | LaTeX+data PreProc = None | Markdown | LaTeX | RST knownExts :: [String] knownExts =@@ -28,6 +28,7 @@ , "tex" , "markdown" , "md"+ , "rst" ] guessPreProc :: FilePath -> PreProc@@ -35,6 +36,7 @@ ".tex" -> LaTeX ".markdown" -> Markdown ".md" -> Markdown+ ".rst" -> RST _ -> None unLit :: PreProc -> Text -> Text@@ -47,6 +49,7 @@ None -> return . Code Markdown -> markdown LaTeX -> latex+ RST -> rst data Block = Code [Text] | Comment [Text]@@ -102,7 +105,7 @@ isOpenFence l | "```" `Text.isPrefixOf` l' =- Just $ case Text.drop 3 l' of+ Just $ case Text.dropWhile isSpace (Text.drop 3 l') of l'' | "cryptol" `Text.isPrefixOf` l'' -> Code | isBlank l'' -> Code | otherwise -> Comment@@ -134,6 +137,35 @@ isBeginCode l = "\\begin{code}" `Text.isPrefixOf` l isEndCode l = "\\end{code}" `Text.isPrefixOf` l +rst :: [Text] -> [Block]+rst = comment []+ where+ isBeginCode l = case filter (not . Text.null) (Text.split isSpace l) of+ ["..", dir, "cryptol"] -> dir == "code-block::" ||+ dir == "sourcecode::"+ _ -> False + isEmpty = Text.all isSpace+ isCode l = case Text.uncons l of+ Just (c, _) -> isSpace c+ Nothing -> True++ comment acc ls =+ case ls of+ [] -> mk Comment acc+ l : ls1 | isBeginCode l -> codeOptions (l : acc) ls1+ | otherwise -> comment (l : acc) ls1++ codeOptions acc ls =+ case ls of+ [] -> mk Comment acc+ l : ls1 | isEmpty l -> mk Comment (l : acc) ++ code [] ls1+ | otherwise -> codeOptions (l : acc) ls1++ code acc ls =+ case ls of+ [] -> mk Code acc+ l : ls1 | isCode l -> code (l : acc) ls1+ | otherwise -> mk Code acc ++ comment [] ls
src/Cryptol/Parser/Utils.hs view
@@ -10,6 +10,7 @@ -- from previous Cryptol versions. {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Safe #-} module Cryptol.Parser.Utils ( translateExprToNumT@@ -41,7 +42,7 @@ return (TInfix e1 o f e2) EParens e -> do t <- translateExprToNumT e- return (TParens t)+ return (TParens t Nothing) _ -> Nothing
src/Cryptol/REPL/Browse.hs view
@@ -13,7 +13,9 @@ import qualified Cryptol.TypeCheck.Type as T import Cryptol.Utils.PP-import Cryptol.ModuleSystem.Env(ModContext(..))+import Cryptol.Utils.Ident (OrigName(..), modPathIsNormal, identIsNormal)++import Cryptol.ModuleSystem.Env(ModContext(..),ModContextParams(..)) import Cryptol.ModuleSystem.NamingEnv(namingEnvNames) import Cryptol.ModuleSystem.Name import Cryptol.ModuleSystem.Interface@@ -21,11 +23,14 @@ data BrowseHow = BrowseExported | BrowseInScope browseModContext :: BrowseHow -> ModContext -> PP.Doc Void-browseModContext how mc = runDoc (env disp) (vcat sections)+browseModContext how mc =+ runDoc (env disp) (vcat sections) where sections = concat [ browseMParams (env disp) (mctxParams mc)+ , browseSignatures disp decls , browseMods disp decls+ , browseFunctors disp decls , browseTSyns disp decls , browsePrimTys disp decls , browseNewtypes disp decls@@ -35,7 +40,12 @@ disp = DispInfo { dispHow = how, env = mctxNameDisp mc } decls = filterIfaceDecls (`Set.member` visNames) (mctxDecls mc) allNames = namingEnvNames (mctxNames mc)- visNames = case how of+ notAnon nm = identIsNormal (nameIdent nm) &&+ case nameModPathMaybe nm of+ Just p -> modPathIsNormal p+ _ -> True -- shouldn't happen?+ visNames = Set.filter notAnon+ case how of BrowseInScope -> allNames BrowseExported -> mctxExported mc @@ -44,33 +54,52 @@ -------------------------------------------------------------------------------- -browseMParams :: NameDisp -> IfaceParams -> [Doc]-browseMParams disp params =- ppSectionHeading "Module Parameters"- $ addEmpty- $ map ppParamTy (sortByName disp (Map.toList (ifParamTypes params))) ++- map ppParamFu (sortByName disp (Map.toList (ifParamFuns params)))+browseMParams :: NameDisp -> ModContextParams -> [Doc]+browseMParams disp pars =+ case pars of+ NoParams -> []+ FunctorParams params ->+ ppSectionHeading "Module Parameters"+ $ [ "parameter" <+> pp (T.mpName p) <+> ":" <+>+ "interface" <+> pp (T.mpIface p) $$+ indent 2 (vcat $+ map ppParamTy (sortByName disp (Map.toList (T.mpnTypes names))) +++ map ppParamFu (sortByName disp (Map.toList (T.mpnFuns names)))+ )+ | p <- Map.elems params+ , let names = T.mpParameters p+ ] +++ [" "]+ InterfaceParams ps -> [pp ps] -- XXX where ppParamTy p = nest 2 (sep ["type", pp (T.mtpName p) <+> ":", pp (T.mtpKind p)]) ppParamFu p = nest 2 (sep [pp (T.mvpName p) <+> ":", pp (T.mvpType p)]) -- XXX: should we print the constraints somewhere too? - addEmpty xs = case xs of- [] -> []- _ -> xs ++ [" "] - browseMods :: DispInfo -> IfaceDecls -> [Doc] browseMods disp decls =- ppSection disp "Modules" ppM (ifModules decls)+ ppSection disp "Submodules" ppM (ifModules decls) where- ppM m = "submodule" <+> pp (ifModName m)- -- XXX: can print a lot more information about the moduels, but- -- might be better to do that with a separate command+ ppM m = pp (ifsName m) +browseFunctors :: DispInfo -> IfaceDecls -> [Doc]+browseFunctors disp decls =+ ppSection disp "Parameterized Submodules" ppM (ifFunctors decls)+ where+ ppM m = pp (ifModName m) ++browseSignatures :: DispInfo -> IfaceDecls -> [Doc]+browseSignatures disp decls =+ ppSection disp "Interface Submodules"+ ppS (Map.mapWithKey (,) (ifSignatures decls))+ where+ ppS (x,s) = pp x++ browseTSyns :: DispInfo -> IfaceDecls -> [Doc] browseTSyns disp decls = ppSection disp "Type Synonyms" pp tss@@ -142,8 +171,8 @@ where toEntry (n,a) = case nameInfo n of- Declared m _ -> Just (m,[(n,a)])- _ -> Nothing+ GlobalName _ og -> Just (ogModule og,[(n,a)])+ _ -> Nothing sortByName :: NameDisp -> [(Name,a)] -> [a]
src/Cryptol/REPL/Command.hs view
@@ -59,19 +59,25 @@ import Cryptol.REPL.Monad import Cryptol.REPL.Trie import Cryptol.REPL.Browse+import Cryptol.REPL.Help import qualified Cryptol.ModuleSystem as M import qualified Cryptol.ModuleSystem.Name as M import qualified Cryptol.ModuleSystem.NamingEnv as M-import qualified Cryptol.ModuleSystem.Renamer as M (RenamerWarning(SymbolShadowed))+import qualified Cryptol.ModuleSystem.Renamer as M+ (RenamerWarning(SymbolShadowed, PrefixAssocChanged)) import qualified Cryptol.Utils.Ident as M import qualified Cryptol.ModuleSystem.Env as M+import Cryptol.ModuleSystem.Fingerprint(fingerprintHexString) +import Cryptol.Backend.FloatHelpers as FP import qualified Cryptol.Backend.Monad as E import qualified Cryptol.Backend.SeqMap as E import Cryptol.Eval.Concrete( Concrete(..) ) import qualified Cryptol.Eval.Concrete as Concrete import qualified Cryptol.Eval.Env as E+import Cryptol.Eval.FFI+import Cryptol.Eval.FFI.GenHeader import qualified Cryptol.Eval.Type as E import qualified Cryptol.Eval.Value as E import qualified Cryptol.Eval.Reference as R@@ -86,7 +92,8 @@ import qualified Cryptol.TypeCheck.Parseable as T import qualified Cryptol.TypeCheck.Subst as T import Cryptol.TypeCheck.Solve(defaultReplExpr)-import Cryptol.TypeCheck.PP (dump,ppWithNames,emptyNameMap)+import Cryptol.TypeCheck.PP (dump)+import qualified Cryptol.Utils.Benchmark as Bench import Cryptol.Utils.PP hiding ((</>)) import Cryptol.Utils.Panic(panic) import Cryptol.Utils.RecordMap@@ -104,28 +111,30 @@ import Control.Monad hiding (mapM, mapM) import qualified Control.Monad.Catch as Ex import Control.Monad.IO.Class(liftIO)+import Text.Read (readMaybe)+import Control.Applicative ((<|>))+import qualified Data.Set as Set import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BS8 import Data.Bits (shiftL, (.&.), (.|.)) import Data.Char (isSpace,isPunctuation,isSymbol,isAlphaNum,isAscii) import Data.Function (on)-import Data.List (intercalate, nub, isPrefixOf,intersperse)+import Data.List (intercalate, nub, isPrefixOf) import Data.Maybe (fromMaybe,mapMaybe,isNothing) import System.Environment (lookupEnv) import System.Exit (ExitCode(ExitSuccess)) import System.Process (shell,createProcess,waitForProcess) import qualified System.Process as Process(runCommand)-import System.FilePath((</>), isPathSeparator)+import System.FilePath((</>), (-<.>), isPathSeparator) import System.Directory(getHomeDirectory,setCurrentDirectory,doesDirectoryExist ,getTemporaryDirectory,setPermissions,removeFile ,emptyPermissions,setOwnerReadable)-import qualified Data.Map as Map-import qualified Data.Set as Set import System.IO (Handle,hFlush,stdout,openTempFile,hClose,openFile ,IOMode(..),hGetContents,hSeek,SeekMode(..))-import System.Random.TF(newTFGen)+import qualified System.Random.TF as TF+import qualified System.Random.TF.Instances as TFI import Numeric (showFFloat) import qualified Data.Text as T import Data.IORef(newIORef,readIORef,writeIORef)@@ -137,6 +146,8 @@ import qualified Data.SBV.Internals as SBV (showTDiff) ++ -- Commands -------------------------------------------------------------------- -- | Commands.@@ -251,6 +262,33 @@ , CommandDescr [ ":extract-coq" ] [] (NoArg allTerms) "Print out the post-typechecked AST of all currently defined terms,\nin a Coq-parseable format." ""+ , CommandDescr [ ":time" ] ["EXPR"] (ExprArg timeCmd)+ "Measure the time it takes to evaluate the given expression."+ (unlines+ [ "The expression will be evaluated many times to get accurate results."+ , "Note that the first evaluation of a binding may take longer due to"+ , " laziness, and this may affect the reported time. If this is not"+ , " desired then make sure to evaluate the expression once first before"+ , " running :time."+ , "The amount of time to spend collecting measurements can be changed"+ , " with the timeMeasurementPeriod option."+ , "Reports the average wall clock time, CPU time, and cycles."+ , " (Cycles are in unspecified units that may be CPU cycles.)"+ , "Binds the result to"+ , " it : { avgTime : Float64"+ , " , avgCpuTime : Float64"+ , " , avgCycles : Integer }" ])++ , CommandDescr [ ":set-seed" ] ["SEED"] (OptionArg seedCmd)+ "Seed the random number generator for operations using randomness"+ (unlines+ [ "A seed takes the form of either a single integer or a 4-tuple"+ , "of unsigned 64-bit integers. Examples of commands using randomness"+ , "are dumpTests and check."+ ])+ , CommandDescr [ ":new-seed"] [] (NoArg newSeedCmd)+ "Randomly generate and set a new seed for the random number generator"+ "" ] commandList :: [CommandDescr]@@ -290,6 +328,23 @@ , "number of tests is determined by the \"tests\" option." ]) ""+ , CommandDescr [ ":generate-foreign-header" ] ["FILE"] (FilenameArg genHeaderCmd)+ "Generate a C header file from foreign declarations in a Cryptol file."+ (unlines+ [ "Converts all foreign declarations in the given Cryptol file into C"+ , "function declarations, and writes them to a file with the same name"+ , "but with a .h extension." ])+++ , CommandDescr [ ":file-deps" ] [ "FILE" ]+ (FilenameArg (moduleInfoCmd True))+ "Show information about the dependencies of a file"+ ""++ , CommandDescr [ ":module-deps" ] [ "MODULE" ]+ (ModNameArg (moduleInfoCmd False))+ "Show information about the dependencies of a module"+ "" ] genHelp :: [CommandDescr] -> [String]@@ -368,14 +423,13 @@ (val, ty) <- replEvalExpr expr ppopts <- getPPValOpts testNum <- getKnownUser "tests" :: REPL Int- g <- io newTFGen tenv <- E.envTypes . M.deEnv <$> getDynEnv let tyv = E.evalValType tenv ty gens <- case TestR.dumpableType tyv of Nothing -> raise (TypeNotTestable ty) Just gens -> return gens- tests <- io $ TestR.returnTests g gens val testNum+ tests <- withRandomGen (\g -> io $ TestR.returnTests' g gens val testNum) out <- forM tests $ \(args, x) -> do argOut <- mapM (rEval . E.ppValue Concrete ppopts) args@@ -431,10 +485,17 @@ T.Schema -> REPL TestReport qcExpr qcMode exprDoc texpr schema =- do (val,ty) <- replEvalCheckedExpr texpr schema+ do (val,ty) <- replEvalCheckedExpr texpr schema >>= \mb_res -> case mb_res of+ Just res -> pure res+ -- If instance is not found, doesn't necessarily mean that there is no instance.+ -- And due to nondeterminism in result from the solver (for finding solution to + -- numeric type constraints), `:check` can get to this exception sometimes, but+ -- successfully find an instance and test with it other times.+ Nothing -> raise (InstantiationsNotFound schema) testNum <- (toInteger :: Int -> Integer) <$> getKnownUser "tests" tenv <- E.envTypes . M.deEnv <$> getDynEnv let tyv = E.evalValType tenv ty+ -- tv has already had polymorphism instantiated percentRef <- io $ newIORef Nothing testsRef <- io $ newIORef 0 @@ -460,11 +521,11 @@ Just (sz,tys,_,gens) | qcMode == QCRandom -> do rPutStrLn "Using random testing." prt testingMsg- g <- io newTFGen (res,num) <-- Ex.catch (randomTests (\n -> ppProgress percentRef testsRef n testNum)- testNum val gens g)- (\ex -> do rPutStrLn "\nTest interrupted..."+ withRandomGen+ (randomTests' (\n -> ppProgress percentRef testsRef n testNum)+ testNum val gens)+ `Ex.catch` (\ex -> do rPutStrLn "\nTest interrupted..." num <- io $ readIORef testsRef let report = TestReport exprDoc Pass num sz ppReport tys False report@@ -801,7 +862,9 @@ printSafetyViolation :: T.Expr -> T.Schema -> [E.GenValue Concrete] -> REPL () printSafetyViolation texpr schema vs = catch- (do (fn,_) <- replEvalCheckedExpr texpr schema+ (do fn <- replEvalCheckedExpr texpr schema >>= \mb_res -> case mb_res of + Just (fn, _) -> pure fn+ Nothing -> raise (EvalPolyError schema) rEval (E.forceValue =<< foldM (\f v -> E.fromVFun Concrete f (pure v)) fn vs)) (\case EvalError eex -> rPutStrLn (show (pp eex))@@ -989,6 +1052,32 @@ rPrint $ runDoc fDisp $ group $ hang (ppPrec 2 expr <+> text ":") 2 (pp sig) +timeCmd :: String -> (Int, Int) -> Maybe FilePath -> REPL ()+timeCmd str pos fnm = do+ period <- getKnownUser "timeMeasurementPeriod" :: REPL Int+ quiet <- getKnownUser "timeQuiet"+ unless quiet $+ rPutStrLn $ "Measuring for " ++ show period ++ " seconds"+ pExpr <- replParseExpr str pos fnm+ (_, def, sig) <- replCheckExpr pExpr+ replPrepareCheckedExpr def sig >>= \case+ Nothing -> raise (EvalPolyError sig)+ Just (_, expr) -> do+ Bench.BenchmarkStats {..} <- liftModuleCmd+ (rethrowEvalError . M.benchmarkExpr (fromIntegral period) expr)+ unless quiet $+ rPutStrLn $ "Avg time: " ++ Bench.secs benchAvgTime+ ++ " Avg CPU time: " ++ Bench.secs benchAvgCpuTime+ ++ " Avg cycles: " ++ show benchAvgCycles+ let mkStatsRec time cpuTime cycles = recordFromFields+ [("avgTime", time), ("avgCpuTime", cpuTime), ("avgCycles", cycles)]+ itType = E.TVRec $ mkStatsRec E.tvFloat64 E.tvFloat64 E.TVInteger+ itVal = E.VRecord $ mkStatsRec+ (pure $ E.VFloat $ FP.floatFromDouble benchAvgTime)+ (pure $ E.VFloat $ FP.floatFromDouble benchAvgCpuTime)+ (pure $ E.VInteger $ toInteger benchAvgCycles)+ bindItVariableVal itType itVal+ readFileCmd :: FilePath -> REPL () readFileCmd fp = do bytes <- replReadFile fp (\err -> rPutStrLn (show err) >> return Nothing)@@ -1062,11 +1151,9 @@ mb <- getLoadedMod case mb of Just lm ->- case lName lm of- Just m | M.isParamInstModName m -> loadHelper (M.loadModuleByName m)- _ -> case lPath lm of- M.InFile f -> loadCmd f- _ -> return ()+ case lPath lm of+ M.InFile f -> loadCmd f+ _ -> return () Nothing -> return () @@ -1127,16 +1214,14 @@ | null modString = return () | otherwise = do case parseModName modString of- Just m- | M.isParamInstModName m -> loadHelper (M.loadModuleByName m)- | otherwise ->- do mpath <- liftModuleCmd (M.findModule m)- case mpath of- M.InFile file ->- do setEditPath file- setLoadedMod LoadedModule { lName = Just m, lPath = mpath }- loadHelper (M.loadModuleByPath file)- M.InMem {} -> loadHelper (M.loadModuleByName m)+ Just m ->+ do mpath <- liftModuleCmd (M.findModule m)+ case mpath of+ M.InFile file ->+ do setEditPath file+ setLoadedMod LoadedModule { lName = Just m, lPath = mpath }+ loadHelper (M.loadModuleByPath file)+ M.InMem {} -> loadHelper (M.loadModuleByName m) Nothing -> rPutStrLn "Invalid module name." loadPrelude :: REPL ()@@ -1153,13 +1238,14 @@ } loadHelper (M.loadModuleByPath path) -loadHelper :: M.ModuleCmd (M.ModulePath,T.Module) -> REPL ()+loadHelper :: M.ModuleCmd (M.ModulePath,T.TCTopEntity) -> REPL () loadHelper how = do clearLoadedMod- (path,m) <- liftModuleCmd how- whenDebug (rPutStrLn (dump m))+ (path,ent) <- liftModuleCmd how++ whenDebug (rPutStrLn (dump ent)) setLoadedMod LoadedModule- { lName = Just (T.mName m)+ { lName = Just (T.tcTopEntitytName ent) , lPath = path } -- after a successful load, the current module becomes the edit target@@ -1168,6 +1254,25 @@ M.InMem {} -> clearEditPath setDynEnv mempty +genHeaderCmd :: FilePath -> REPL ()+genHeaderCmd path+ | null path = pure ()+ | otherwise = do+ (mPath, m) <- liftModuleCmd $ M.checkModuleByPath path+ let decls = case m of+ T.TCTopModule mo -> findForeignDecls mo+ T.TCTopSignature {} -> []+ if null decls+ then rPutStrLn $ "No foreign declarations in " ++ pretty mPath+ else do+ let header = generateForeignHeader decls+ case mPath of+ M.InFile p -> do+ let hPath = p -<.> "h"+ rPutStrLn $ "Writing header to " ++ hPath+ replWriteFileString hPath header (rPutStrLn . show)+ M.InMem _ _ -> rPutStrLn header+ versionCmd :: REPL () versionCmd = displayVersion rPutStrLn @@ -1230,153 +1335,10 @@ cs -> void $ runCommand 1 Nothing (Ambiguous cmd0 (concatMap cNames cs)) | otherwise = case parseHelpName cmd of- Just qname ->- do fe <- getFocusedEnv- let params = M.mctxParams fe- env = M.mctxDecls fe- rnEnv = M.mctxNames fe- disp = M.mctxNameDisp fe-- vNames = M.lookupValNames qname rnEnv- tNames = M.lookupTypeNames qname rnEnv- mNames = M.lookupNS M.NSModule qname rnEnv-- let helps = map (showTypeHelp params env disp) tNames ++- map (showValHelp params env disp qname) vNames ++- map (showModHelp env disp) mNames-- separ = rPutStrLn " ---------"- sequence_ (intersperse separ helps)-- when (null (vNames ++ tNames ++ mNames)) $- rPrint $ "Undefined name:" <+> pp qname- Nothing ->- rPutStrLn ("Unable to parse name: " ++ cmd)+ Just qname -> helpForNamed qname+ Nothing -> rPutStrLn ("Unable to parse name: " ++ cmd) where- noInfo nameEnv name =- case M.nameInfo name of- M.Declared m _ ->- rPrint $ runDoc nameEnv ("Name defined in module" <+> pp m)- M.Parameter -> rPutStrLn "// No documentation is available."--- showModHelp _env disp x =- rPrint $ runDoc disp $ vcat [ "`" <> pp x <> "` is a module." ]- -- XXX: show doc. if any-- showTypeHelp params env nameEnv name =- fromMaybe (noInfo nameEnv name) $- msum [ fromTySyn, fromPrimType, fromNewtype, fromTyParam ]-- where- fromTySyn =- do ts <- Map.lookup name (M.ifTySyns env)- return (doShowTyHelp nameEnv (pp ts) (T.tsDoc ts))-- fromNewtype =- do nt <- Map.lookup name (M.ifNewtypes env)- let decl = pp nt $$ (pp name <+> text ":" <+> pp (T.newtypeConType nt))- return $ doShowTyHelp nameEnv decl (T.ntDoc nt)-- fromPrimType =- do a <- Map.lookup name (M.ifAbstractTypes env)- pure $ do rPutStrLn ""- rPrint $ runDoc nameEnv $ nest 4- $ "primitive type" <+> pp (T.atName a)- <+> ":" <+> pp (T.atKind a)-- let (vs,cs) = T.atCtrs a- unless (null cs) $- do let example = T.TCon (T.abstractTypeTC a)- (map (T.TVar . T.tpVar) vs)- ns = T.addTNames vs emptyNameMap- rs = [ "•" <+> ppWithNames ns c | c <- cs ]- rPutStrLn ""- rPrint $ runDoc nameEnv $ indent 4 $- backticks (ppWithNames ns example) <+>- "requires:" $$ indent 2 (vcat rs)-- doShowFix (T.atFixitiy a)- doShowDocString (T.atDoc a)-- fromTyParam =- do p <- Map.lookup name (M.ifParamTypes params)- let uses c = T.TVBound (T.mtpParam p) `Set.member` T.fvs c- ctrs = filter uses (map P.thing (M.ifParamConstraints params))- ctrDoc = case ctrs of- [] -> []- [x] -> [pp x]- xs -> [parens $ commaSep $ map pp xs]- decl = vcat $- [ text "parameter" <+> pp name <+> text ":"- <+> pp (T.mtpKind p) ]- ++ ctrDoc- return $ doShowTyHelp nameEnv decl (T.mtpDoc p)-- doShowTyHelp nameEnv decl doc =- do rPutStrLn ""- rPrint (runDoc nameEnv (nest 4 decl))- doShowDocString doc-- doShowFix fx =- case fx of- Just f ->- let msg = "Precedence " ++ show (P.fLevel f) ++ ", " ++- (case P.fAssoc f of- P.LeftAssoc -> "associates to the left."- P.RightAssoc -> "associates to the right."- P.NonAssoc -> "does not associate.")-- in rPutStrLn ('\n' : msg)-- Nothing -> return ()-- showValHelp params env nameEnv qname name =- fromMaybe (noInfo nameEnv name)- (msum [ fromDecl, fromNewtype, fromParameter ])- where- fromDecl =- do M.IfaceDecl { .. } <- Map.lookup name (M.ifDecls env)- return $- do rPutStrLn ""-- let property- | P.PragmaProperty `elem` ifDeclPragmas = [text "property"]- | otherwise = []- rPrint $ runDoc nameEnv- $ indent 4- $ hsep-- $ property ++ [pp qname, colon, pp (ifDeclSig)]-- doShowFix $ ifDeclFixity `mplus`- (guard ifDeclInfix >> return P.defaultFixity)-- doShowDocString ifDeclDoc-- fromNewtype =- do _ <- Map.lookup name (M.ifNewtypes env)- return $ return ()-- fromParameter =- do p <- Map.lookup name (M.ifParamFuns params)- return $- do rPutStrLn ""- rPrint $ runDoc nameEnv- $ indent 4- $ text "parameter" <+> pp qname- <+> colon- <+> pp (T.mvpType p)-- doShowFix (T.mvpFixity p)- doShowDocString (T.mvpDoc p)-- doShowDocString doc =- case doc of- Nothing -> pure ()- Just d -> rPutStrLn ('\n' : T.unpack d)- showCmdHelp c [arg] | ":set" `elem` cNames c = showOptionHelp arg showCmdHelp c _args = do rPutStrLn ("\n " ++ intercalate ", " (cNames c) ++ " " ++ intercalate " " (cArgs c))@@ -1482,32 +1444,46 @@ } moduleCmdResult =<< io (cmd minp) +-- TODO: add filter for my exhaustie prop guards warning here+ moduleCmdResult :: M.ModuleRes a -> REPL a moduleCmdResult (res,ws0) = do- warnDefaulting <- getKnownUser "warnDefaulting"- warnShadowing <- getKnownUser "warnShadowing"+ warnDefaulting <- getKnownUser "warnDefaulting"+ warnShadowing <- getKnownUser "warnShadowing"+ warnPrefixAssoc <- getKnownUser "warnPrefixAssoc"+ warnNonExhConGrds <- getKnownUser "warnNonExhaustiveConstraintGuards" -- XXX: let's generalize this pattern- let isDefaultWarn (T.DefaultingTo _ _) = True- isDefaultWarn _ = False-- filterDefaults w | warnDefaulting = Just w- filterDefaults (M.TypeCheckWarnings nameMap xs) =- case filter (not . isDefaultWarn . snd) xs of- [] -> Nothing- ys -> Just (M.TypeCheckWarnings nameMap ys)- filterDefaults w = Just w-- isShadowWarn (M.SymbolShadowed {}) = True+ let isShadowWarn (M.SymbolShadowed {}) = True isShadowWarn _ = False - filterShadowing w | warnShadowing = Just w- filterShadowing (M.RenamerWarnings xs) =- case filter (not . isShadowWarn) xs of+ isPrefixAssocWarn (M.PrefixAssocChanged {}) = True+ isPrefixAssocWarn _ = False++ filterRenamer True _ w = Just w+ filterRenamer _ check (M.RenamerWarnings xs) =+ case filter (not . check) xs of [] -> Nothing ys -> Just (M.RenamerWarnings ys)- filterShadowing w = Just w+ filterRenamer _ _ w = Just w - let ws = mapMaybe filterDefaults . mapMaybe filterShadowing $ ws0+ -- ignore certain warnings during typechecking+ filterTypecheck :: M.ModuleWarning -> Maybe M.ModuleWarning+ filterTypecheck (M.TypeCheckWarnings nameMap xs) = + case filter (allow . snd) xs of + [] -> Nothing+ ys -> Just (M.TypeCheckWarnings nameMap ys)+ where+ allow :: T.Warning -> Bool + allow = \case+ T.DefaultingTo _ _ | not warnDefaulting -> False+ T.NonExhaustivePropGuards _ | not warnNonExhConGrds -> False+ _ -> True+ filterTypecheck w = Just w++ let ws = mapMaybe (filterRenamer warnShadowing isShadowWarn)+ . mapMaybe (filterRenamer warnPrefixAssoc isPrefixAssocWarn)+ . mapMaybe filterTypecheck+ $ ws0 names <- M.mctxNameDisp <$> getFocusedEnv mapM_ (rPrint . runDoc names . pp) ws case res of@@ -1552,39 +1528,47 @@ replEvalExpr :: P.Expr P.PName -> REPL (Concrete.Value, T.Type) replEvalExpr expr = do (_,def,sig) <- replCheckExpr expr- replEvalCheckedExpr def sig+ replEvalCheckedExpr def sig >>= \case+ Just res -> pure res+ Nothing -> raise (EvalPolyError sig) -replEvalCheckedExpr :: T.Expr -> T.Schema -> REPL (Concrete.Value, T.Type)+replEvalCheckedExpr :: T.Expr -> T.Schema -> REPL (Maybe (Concrete.Value, T.Type)) replEvalCheckedExpr def sig =- do validEvalContext def- validEvalContext sig+ replPrepareCheckedExpr def sig >>=+ traverse \(tys, def1) -> do+ let su = T.listParamSubst tys+ let ty = T.apSubst su (T.sType sig)+ whenDebug (rPutStrLn (dump def1)) - s <- getTCSolver- mbDef <- io (defaultReplExpr s def sig)+ tenv <- E.envTypes . M.deEnv <$> getDynEnv+ let tyv = E.evalValType tenv ty - (def1,ty) <-- case mbDef of- Nothing -> raise (EvalPolyError sig)- Just (tys,def1) ->- do warnDefaults tys- let su = T.listParamSubst tys- return (def1, T.apSubst su (T.sType sig))+ -- add "it" to the namespace via a new declaration+ itVar <- bindItVariable tyv def1 - whenDebug (rPutStrLn (dump def1))+ let itExpr = case getLoc def of+ Nothing -> T.EVar itVar+ Just rng -> T.ELocated rng (T.EVar itVar) - tenv <- E.envTypes . M.deEnv <$> getDynEnv- let tyv = E.evalValType tenv ty+ -- evaluate the it variable+ val <- liftModuleCmd (rethrowEvalError . M.evalExpr itExpr)+ return (val,ty) - -- add "it" to the namespace via a new declaration- itVar <- bindItVariable tyv def1+-- | Check that we are in a valid evaluation context and apply defaulting.+replPrepareCheckedExpr :: T.Expr -> T.Schema ->+ REPL (Maybe ([(T.TParam, T.Type)], T.Expr))+replPrepareCheckedExpr def sig = do+ validEvalContext def+ validEvalContext sig - let itExpr = case getLoc def of- Nothing -> T.EVar itVar- Just rng -> T.ELocated rng (T.EVar itVar)+ s <- getTCSolver+ mbDef <- io (defaultReplExpr s def sig) - -- evaluate the it variable- val <- liftModuleCmd (rethrowEvalError . M.evalExpr itExpr)- return (val,ty)+ case mbDef of+ Nothing -> pure Nothing+ Just (tys, def1) -> do+ warnDefaults tys+ pure $ Just (tys, def1) where warnDefaults ts = case ts of@@ -1600,8 +1584,15 @@ itIdent = M.packIdent "it" replWriteFile :: FilePath -> BS.ByteString -> (X.SomeException -> REPL ()) -> REPL ()-replWriteFile fp bytes handler =- do x <- io $ X.catch (BS.writeFile fp bytes >> return Nothing) (return . Just)+replWriteFile = replWriteFileWith BS.writeFile++replWriteFileString :: FilePath -> String -> (X.SomeException -> REPL ()) -> REPL ()+replWriteFileString = replWriteFileWith writeFile++replWriteFileWith :: (FilePath -> a -> IO ()) -> FilePath -> a ->+ (X.SomeException -> REPL ()) -> REPL ()+replWriteFileWith write fp contents handler =+ do x <- io $ X.catch (write fp contents >> return Nothing) (return . Just) maybe (return ()) handler x replReadFile :: FilePath -> (X.SomeException -> REPL (Maybe BS.ByteString)) -> REPL (Maybe BS.ByteString)@@ -1629,7 +1620,7 @@ } liftModuleCmd (M.evalDecls [T.NonRecursive decl]) denv <- getDynEnv- let nenv' = M.singletonE (P.UnQual itIdent) freshIt+ let nenv' = M.singletonNS M.NSValue (P.UnQual itIdent) freshIt `M.shadowing` M.deNames denv setDynEnv $ denv { M.deNames = nenv' } return freshIt@@ -1675,7 +1666,32 @@ type CommandMap = Trie CommandDescr +newSeedCmd :: REPL ()+newSeedCmd =+ do seed <- createAndSetSeed+ rPutStrLn "Seed initialized to:"+ rPutStrLn (show seed)+ where+ createAndSetSeed =+ withRandomGen $ \g0 ->+ let (s1, g1) = TFI.random g0+ (s2, g2) = TFI.random g1+ (s3, g3) = TFI.random g2+ (s4, _) = TFI.random g3+ seed = (s1, s2, s3, s4)+ in pure (seed, TF.seedTFGen seed) +seedCmd :: String -> REPL ()+seedCmd s =+ case mbGen of+ Nothing -> rPutStrLn "Could not parse seed argument - expecting an integer or 4-tuple of integers."+ Just gen -> setRandomGen gen++ where+ mbGen =+ (TF.mkTFGen <$> readMaybe s)+ <|> (TF.seedTFGen <$> readMaybe s)+ -- Command Parsing ------------------------------------------------------------- -- | Strip leading space.@@ -1774,3 +1790,42 @@ '"':rest -> Just $ quoted '"' rest _ -> let (a,b) = break isSpace ipt in if null a then Nothing else Just (length a, a, b)++++moduleInfoCmd :: Bool -> String -> REPL ()+moduleInfoCmd isFile name+ | isFile = showInfo =<< liftModuleCmd (M.getFileDependencies name)+ | otherwise =+ case parseModName name of+ Just m -> showInfo =<< liftModuleCmd (M.getModuleDependencies m)+ Nothing -> rPutStrLn "Invalid module name."++ where+ showInfo (p,fi) =+ do rPutStr "{ \"source\": "+ case p of+ M.InFile f -> rPutStrLn (show f)+ M.InMem l _ -> rPutStrLn ("{ \"internal\": " ++ show l ++ " }")++ rPutStrLn (", \"fingerprint\": \"0x" +++ fingerprintHexString (M.fiFingerprint fi) ++ "\"")++ let depList f x ys =+ do rPutStr (", " ++ show (x :: String) ++ ":")+ case ys of+ [] -> rPutStrLn " []"+ i : is ->+ do rPutStrLn ""+ rPutStrLn (" [ " ++ f i)+ mapM_ (\j -> rPutStrLn (" , " ++ f j)) is+ rPutStrLn " ]"++ depList show "includes" (Set.toList (M.fiIncludeDeps fi))+ depList (show . show . pp) "imports" (Set.toList (M.fiImportDeps fi))+ depList show "foreign" (Set.toList (M.fiForeignDeps fi))++ rPutStrLn "}"+++
+ src/Cryptol/REPL/Help.hs view
@@ -0,0 +1,379 @@+{-# Language BlockArguments #-}+{-# Language OverloadedStrings #-}+{-# Language RecordWildCards #-}+module Cryptol.REPL.Help (helpForNamed) where++import Data.Text (Text)+import qualified Data.Text as Text+import Data.Map (Map)+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Maybe(fromMaybe)+import Data.List(intersperse)+import Control.Monad(when,guard,unless,msum,mplus)++import Cryptol.Utils.PP+import Cryptol.Utils.Ident(OrigName(..),identIsNormal)+import qualified Cryptol.Parser.AST as P+import qualified Cryptol.ModuleSystem as M+import qualified Cryptol.ModuleSystem.Name as M+import qualified Cryptol.ModuleSystem.NamingEnv as M+import qualified Cryptol.ModuleSystem.Env as M+import qualified Cryptol.ModuleSystem.Interface as M+import qualified Cryptol.ModuleSystem.Renamer.Error as M (ModKind(..))+import qualified Cryptol.TypeCheck.AST as T+import Cryptol.TypeCheck.PP(emptyNameMap,ppWithNames)++import Cryptol.REPL.Monad++helpForNamed :: P.PName -> REPL ()+helpForNamed qname =+ do fe <- getFocusedEnv+ let params = M.mctxParams fe+ env = M.mctxDecls fe+ rnEnv = M.mctxNames fe+ disp = M.mctxNameDisp fe++ vNames = M.lookupListNS M.NSValue qname rnEnv+ tNames = M.lookupListNS M.NSType qname rnEnv+ mNames = M.lookupListNS M.NSModule qname rnEnv++ let helps = map (showTypeHelp params env disp) tNames +++ map (showValHelp params env disp qname) vNames +++ map (showModHelp env disp) mNames++ separ = rPutStrLn " ---------"+ sequence_ (intersperse separ helps)++ when (null (vNames ++ tNames ++ mNames)) $+ rPrint $ "Undefined name:" <+> pp qname+++noInfo :: NameDisp -> M.Name -> REPL ()+noInfo nameEnv name =+ case M.nameInfo name of+ M.GlobalName _ og ->+ rPrint (runDoc nameEnv ("Name defined in module" <+> pp (ogModule og)))+ M.LocalName {} -> rPutStrLn "// No documentation is available."+++-- | Show help for something in the module namespace.+showModHelp :: M.IfaceDecls -> NameDisp -> M.Name -> REPL ()+showModHelp env nameEnv name =+ fromMaybe (noInfo nameEnv name) $+ msum [ attempt M.ifModules showModuleHelp+ , attempt M.ifFunctors showFunctorHelp+ , attempt M.ifSignatures showSigHelp+ ]++ where+ attempt :: (M.IfaceDecls -> Map M.Name a) ->+ (M.IfaceDecls -> NameDisp -> M.Name -> a -> REPL ()) ->+ Maybe (REPL ())+ attempt inMap doShow =+ do th <- Map.lookup name (inMap env)+ pure (doShow env nameEnv name th)++showModuleHelp ::+ M.IfaceDecls -> NameDisp -> M.Name -> M.IfaceNames M.Name -> REPL ()+showModuleHelp env _nameEnv name info =+ showSummary M.AModule name (M.ifsDoc info) (ifaceSummary env info)++ifaceSummary :: M.IfaceDecls -> M.IfaceNames M.Name -> ModSummary+ifaceSummary env info =+ foldr addName emptySummary (Set.toList (M.ifsPublic info))+ where+ addName x ns = fromMaybe ns+ $ msum [ addT <$> msum [fromTS, fromNT, fromAT]+ , addV <$> fromD+ , addM <$> msum [ fromM, fromS, fromF ]+ ]+ where+ addT (k,d) = ns { msTypes = T.ModTParam { T.mtpName = x+ , T.mtpKind = k+ , T.mtpDoc = d+ } : msTypes ns }++ addV (t,d,f) = ns { msVals = T.ModVParam { T.mvpName = x+ , T.mvpType = t+ , T.mvpDoc = d+ , T.mvpFixity = f+ } : msVals ns }++ addM (k,d)= ns { msMods = (x, k, d) : msMods ns }+++ fromTS = do def <- Map.lookup x (M.ifTySyns env)+ pure (T.kindOf def, T.tsDoc def)++ fromNT = do def <- Map.lookup x (M.ifNewtypes env)+ pure (T.kindOf def, T.ntDoc def)++ fromAT = do def <- Map.lookup x (M.ifAbstractTypes env)+ pure (T.kindOf def, T.atDoc def)++ fromD = do def <- Map.lookup x (M.ifDecls env)+ pure (M.ifDeclSig def, M.ifDeclDoc def, M.ifDeclFixity def)++ fromM = do def <- Map.lookup x (M.ifModules env)+ pure (M.AModule, M.ifsDoc def)++ fromF = do def <- Map.lookup x (M.ifFunctors env)+ pure (M.AFunctor, M.ifsDoc (M.ifNames def))++ fromS = do def <- Map.lookup x (M.ifSignatures env)+ pure (M.ASignature, T.mpnDoc def)++++showFunctorHelp ::+ M.IfaceDecls -> NameDisp -> M.Name -> M.IfaceG M.Name -> REPL ()+showFunctorHelp _env _nameEnv name info =+ showSummary M.AFunctor name (M.ifsDoc ns) summary+ where+ ns = M.ifNames info+ summary = (ifaceSummary (M.ifDefines info) ns)+ { msParams = [ (T.mpName p, T.mpIface p)+ | p <- Map.elems (M.ifParams info)+ ]+ }+++showSigHelp ::+ M.IfaceDecls -> NameDisp -> M.Name -> T.ModParamNames -> REPL ()+showSigHelp _env _nameEnv name info =+ showSummary M.ASignature name (T.mpnDoc info)+ emptySummary+ { msTypes = Map.elems (T.mpnTypes info)+ , msVals = Map.elems (T.mpnFuns info)+ , msConstraints = map P.thing (T.mpnConstraints info)+ }++--------------------------------------------------------------------------------+data ModSummary = ModSummary+ { msParams :: [(P.Ident, P.ImpName M.Name)]+ , msConstraints :: [T.Prop]+ , msTypes :: [T.ModTParam]+ , msVals :: [T.ModVParam]+ , msMods :: [ (M.Name, M.ModKind, Maybe Text) ]+ }++emptySummary :: ModSummary+emptySummary = ModSummary+ { msParams = []+ , msConstraints = []+ , msTypes = []+ , msVals = []+ , msMods = []+ }++showSummary :: M.ModKind -> M.Name -> Maybe Text -> ModSummary -> REPL ()+showSummary k name doc info =+ do rPutStrLn ""++ rPrint $ runDoc disp+ case k of+ M.AModule ->+ vcat [ "Module" <+> pp name <+> "exports:"+ , indent 2 $ vcat [ ppTPs, ppFPs ]+ ]+ M.ASignature ->+ vcat [ "Interface" <+> pp name <+> "requires:"+ , indent 2 $ vcat [ ppTPs, ppCtrs, ppFPs ]+ ]+ M.AFunctor ->+ vcat [ "Parameterized module" <+> pp name <+> "requires:"+ , indent 2 $ ppPs+ , " ", "and exports:"+ , indent 2 $ vcat [ ppTPs, ppFPs ]+ ]++ doShowDocString doc++ where+ -- qualifying stuff is too noisy+ disp = NameDisp \_ -> Just UnQualified++ withMaybeNest mb x =+ case mb of+ Nothing -> x+ Just d -> vcat [x, indent 2 d]++ withDoc mb = withMaybeNest (pp <$> mb)+ withFix mb = withMaybeNest (text . ppFixity <$> mb)+ ppMany xs = case xs of+ [] -> mempty+ _ -> vcat (" " : xs)++ ppPs = ppMany (map ppP (msParams info))+ ppP (x,y)+ | identIsNormal x = pp x <+> ": interface" <+> pp y+ | otherwise = "(anonymous parameter)"+++ ppTPs = ppMany (map ppTP (msTypes info))+ ppTP x = withDoc (T.mtpDoc x)+ $ hsep ["type", pp (T.mtpName x), ":", pp (T.mtpKind x)]++ ppCtrs = ppMany (map pp (msConstraints info))++ ppFPs = ppMany (map ppFP (msVals info))+ ppFP x = withFix (T.mvpFixity x)+ $ withDoc (T.mvpDoc x)+ $ hsep [pp (T.mvpName x), ":" <+> pp (T.mvpType x) ]+--------------------------------------------------------------------------------+++++showTypeHelp ::+ M.ModContextParams -> M.IfaceDecls -> NameDisp -> T.Name -> REPL ()+showTypeHelp ctxparams env nameEnv name =+ fromMaybe (noInfo nameEnv name) $+ msum [ fromTySyn, fromPrimType, fromNewtype, fromTyParam ]++ where+ fromTySyn =+ do ts <- msum [ Map.lookup name (M.ifTySyns env)+ , Map.lookup name+ (T.mpnTySyn (M.modContextParamNames ctxparams))+ ]+ return (doShowTyHelp nameEnv (pp ts) (T.tsDoc ts))++ fromNewtype =+ do nt <- Map.lookup name (M.ifNewtypes env)+ let decl = pp nt $$ (pp name <+> text ":" <+> pp (T.newtypeConType nt))+ return $ doShowTyHelp nameEnv decl (T.ntDoc nt)++ fromPrimType =+ do a <- Map.lookup name (M.ifAbstractTypes env)+ pure $ do rPutStrLn ""+ rPrint $ runDoc nameEnv $ nest 4+ $ "primitive type" <+> pp (T.atName a)+ <+> ":" <+> pp (T.atKind a)++ let (vs,cs) = T.atCtrs a+ unless (null cs) $+ do let example = T.TCon (T.abstractTypeTC a)+ (map (T.TVar . T.tpVar) vs)+ ns = T.addTNames vs emptyNameMap+ rs = [ "•" <+> ppWithNames ns c | c <- cs ]+ rPutStrLn ""+ rPrint $ runDoc nameEnv $ indent 4 $+ backticks (ppWithNames ns example) <+>+ "requires:" $$ indent 2 (vcat rs)++ doShowFix (T.atFixitiy a)+ doShowDocString (T.atDoc a)++ allParamNames =+ case ctxparams of+ M.NoParams -> mempty+ M.FunctorParams fparams ->+ Map.unions+ [ (\x -> (Just p,x)) <$> T.mpnTypes (T.mpParameters ps)+ | (p, ps) <- Map.toList fparams+ ]+ M.InterfaceParams ps -> (\x -> (Nothing ,x)) <$> T.mpnTypes ps++ fromTyParam =+ do (x,p) <- Map.lookup name allParamNames+ pure do rPutStrLn ""+ case x of+ Just src -> doShowParameterSource src+ Nothing -> pure ()+ let ty = "type" <+> pp name <+> ":" <+> pp (T.mtpKind p)+ rPrint (runDoc nameEnv (indent 4 ty))+ doShowDocString (T.mtpDoc p)+++doShowTyHelp :: NameDisp -> Doc -> Maybe Text -> REPL ()+doShowTyHelp nameEnv decl doc =+ do rPutStrLn ""+ rPrint (runDoc nameEnv (nest 4 decl))+ doShowDocString doc++++showValHelp ::+ M.ModContextParams -> M.IfaceDecls -> NameDisp -> P.PName -> T.Name -> REPL ()++showValHelp ctxparams env nameEnv qname name =+ fromMaybe (noInfo nameEnv name)+ (msum [ fromDecl, fromNewtype, fromParameter ])+ where+ fromDecl =+ do M.IfaceDecl { .. } <- Map.lookup name (M.ifDecls env)+ return $+ do rPutStrLn ""++ let property + | P.PragmaProperty `elem` ifDeclPragmas = [text "property"]+ | otherwise = []+ rPrint $ runDoc nameEnv+ $ indent 4+ $ hsep++ $ property ++ [pp qname, colon, pp (ifDeclSig)]++ doShowFix $ ifDeclFixity `mplus`+ (guard ifDeclInfix >> return P.defaultFixity)++ doShowDocString ifDeclDoc++ fromNewtype =+ do _ <- Map.lookup name (M.ifNewtypes env)+ return $ return ()++ allParamNames =+ case ctxparams of+ M.NoParams -> mempty+ M.FunctorParams fparams ->+ Map.unions+ [ (\x -> (Just p,x)) <$> T.mpnFuns (T.mpParameters ps)+ | (p, ps) <- Map.toList fparams+ ]+ M.InterfaceParams ps -> (\x -> (Nothing,x)) <$> T.mpnFuns ps++ fromParameter =+ do (x,p) <- Map.lookup name allParamNames+ pure do rPutStrLn ""+ case x of+ Just src -> doShowParameterSource src+ Nothing -> pure ()+ let ty = pp name <+> ":" <+> pp (T.mvpType p)+ rPrint (runDoc nameEnv (indent 4 ty))+ doShowFix (T.mvpFixity p)+ doShowDocString (T.mvpDoc p)+++doShowParameterSource :: P.Ident -> REPL ()+doShowParameterSource i =+ do rPutStrLn (Text.unpack msg)+ rPutStrLn ""+ where+ msg+ | identIsNormal i = "Provided by module parameter " <> P.identText i <> "."+ | otherwise = "Provided by `parameters` declaration."+++doShowDocString :: Maybe Text -> REPL ()+doShowDocString doc =+ case doc of+ Nothing -> pure ()+ Just d -> rPutStrLn ('\n' : Text.unpack d)++ppFixity :: T.Fixity -> String+ppFixity f = "Precedence " ++ show (P.fLevel f) ++ ", " +++ case P.fAssoc f of+ P.LeftAssoc -> "associates to the left."+ P.RightAssoc -> "associates to the right."+ P.NonAssoc -> "does not associate."++doShowFix :: Maybe T.Fixity -> REPL ()+doShowFix fx =+ case fx of+ Just f -> rPutStrLn ('\n' : ppFixity f)+ Nothing -> return ()++
src/Cryptol/REPL/Monad.hs view
@@ -15,6 +15,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-} module Cryptol.REPL.Monad ( -- * REPL Monad@@ -57,6 +58,9 @@ , validEvalContext , updateREPLTitle , setUpdateREPLTitle+ , withRandomGen+ , setRandomGen+ , getRandomGen -- ** Config Options , EnvVal(..)@@ -131,6 +135,7 @@ import Text.Read (readMaybe) import Data.SBV (SBVException)+import qualified System.Random.TF as TF import Prelude () import Prelude.Compat@@ -186,6 +191,9 @@ -- Used as a kind of id for the current solver, which helps avoid -- a race condition where the callback of a dead solver runs after -- a new one has been started.++ , eRandomGen :: TF.TFGen+ -- ^ Random number generator for things like QC and dumpTests } @@ -193,6 +201,7 @@ defaultRW :: Bool -> Bool -> Logger -> IO RW defaultRW isBatch callStacks l = do env <- M.initialModuleEnv+ rng <- TF.newTFGen let searchPath = M.meSearchPath env let solverConfig = T.defaultSolverConfig searchPath return RW@@ -209,6 +218,7 @@ , eTCConfig = solverConfig , eTCSolver = Nothing , eTCSolverRestarts = 0+ , eRandomGen = rng } -- | Build up the prompt for the REPL.@@ -224,10 +234,11 @@ case lName =<< eLoadedMod rw of Nothing -> show (pp I.preludeName) Just m- | M.isLoadedParamMod m (M.meLoadedModules (eModuleEnv rw)) ->- modName ++ "(parameterized)"+ | M.isLoadedParamMod m loaded -> modName ++ "(parameterized)"+ | M.isLoadedInterface m loaded -> modName ++ "(interface)" | otherwise -> modName where modName = pretty m+ loaded = M.meLoadedModules (eModuleEnv rw) withFocus = case eLoadedMod rw of@@ -329,8 +340,9 @@ | Unsupported Unsupported | ModuleSystemError NameDisp M.ModuleError | EvalPolyError T.Schema+ | InstantiationsNotFound T.Schema | TypeNotTestable T.Type- | EvalInParamModule [M.Name]+ | EvalInParamModule [T.TParam] [M.Name] | SBVError String | SBVException SBVException | SBVPortfolioException SBVPortfolioException@@ -358,10 +370,13 @@ TooWide e -> pp e EvalPolyError s -> text "Cannot evaluate polymorphic value." $$ text "Type:" <+> pp s+ InstantiationsNotFound s -> text "Cannot find instantiations for some type variables."+ $$ text "Type:" <+> pp s TypeNotTestable t -> text "The expression is not of a testable type." $$ text "Type:" <+> pp t- EvalInParamModule xs -> nest 2 $ vsep $+ EvalInParamModule as xs -> nest 2 $ vsep $ [ text "Expression depends on definitions from a parameterized module:" ]+ ++ map pp as ++ map pp xs SBVError s -> text "SBV error:" $$ text s SBVException e -> text "SBV exception:" $$ text (show e)@@ -552,17 +567,20 @@ let ds = T.freeVars a badVals = foldr badName Set.empty (T.valDeps ds) bad = foldr badName badVals (T.tyDeps ds)+ badTs = T.tyParams ds badName nm bs = case M.nameInfo nm of- M.Declared (M.TopModule m) _ -- XXX: can we focus nested modules?- | M.isLoadedParamMod m (M.meLoadedModules me) -> Set.insert nm bs- _ -> bs - unless (Set.null bad) $- raise (EvalInParamModule (Set.toList bad))+ -- XXX: Changes if focusing on nested modules+ M.GlobalName _ I.OrigName { ogModule = I.TopModule m }+ | M.isLoadedParamMod m (M.meLoadedModules me) -> Set.insert nm bs+ | M.isLoadedInterface m (M.meLoadedModules me) -> Set.insert nm bs + _ -> bs + unless (Set.null bad && Set.null badTs) $+ raise (EvalInParamModule (Set.toList badTs) (Set.toList bad)) -- | Update the title updateREPLTitle :: REPL ()@@ -649,7 +667,19 @@ me <- getModuleEnv setModuleEnv (me { M.meDynEnv = denv }) +getRandomGen :: REPL TF.TFGen+getRandomGen = eRandomGen <$> getRW +setRandomGen :: TF.TFGen -> REPL ()+setRandomGen rng = modifyRW_ (\s -> s { eRandomGen = rng })++withRandomGen :: (TF.TFGen -> REPL (a, TF.TFGen)) -> REPL a+withRandomGen repl =+ do g <- getRandomGen+ (result, g') <- repl g+ setRandomGen g'+ pure result+ -- | Given an existing qualified name, prefix it with a -- relatively-unique string. We make it unique by prefixing with a -- character @#@ that is not lexically valid in a module name.@@ -657,11 +687,12 @@ uniqify name = case M.nameInfo name of- M.Declared ns s ->+ M.GlobalName s og -> M.liftSupply (M.mkDeclared (M.nameNamespace name)- ns s (M.nameIdent name) (M.nameFixity name) (M.nameLoc name))+ (I.ogModule og) s+ (M.nameIdent name) (M.nameFixity name) (M.nameLoc name)) - M.Parameter ->+ M.LocalName {} -> panic "[REPL] uniqify" ["tried to uniqify a parameter: " ++ pretty name] @@ -895,8 +926,12 @@ "Choose whether to display warnings when defaulting." , simpleOpt "warnShadowing" ["warn-shadowing"] (EnvBool True) noCheck "Choose whether to display warnings when shadowing symbols."+ , simpleOpt "warnPrefixAssoc" ["warn-prefix-assoc"] (EnvBool True) noCheck+ "Choose whether to display warnings when expression association has changed due to new prefix operator fixities." , simpleOpt "warnUninterp" ["warn-uninterp"] (EnvBool True) noCheck "Choose whether to issue a warning when uninterpreted functions are used to implement primitives in the symbolic simulator."+ , simpleOpt "warnNonExhaustiveConstraintGuards" ["warn-nonexhaustive-constraintguards"] (EnvBool True) noCheck+ "Choose whether to issue a warning when a use of constraint guards is not determined to be exhaustive." , simpleOpt "smtFile" ["smt-file"] (EnvString "-") noCheck "The file to use for SMT-Lib scripts (for debugging or offline proving).\nUse \"-\" for stdout." , OptionDescr "path" [] (EnvString "") noCheck@@ -978,6 +1013,18 @@ , " * display try to match the order they were written in the source code" , " * canonical use a predictable, canonical order" ]++ , simpleOpt "timeMeasurementPeriod" ["time-measurement-period"] (EnvNum 10)+ checkTimeMeasurementPeriod+ $ unlines+ [ "The period of time in seconds to spend collecting measurements when"+ , " running :time."+ , "This is a lower bound and the actual time taken might be higher if the"+ , " evaluation takes a long time."+ ]++ , simpleOpt "timeQuiet" ["time-quiet"] (EnvBool False) noCheck+ "Suppress output of :time command and only bind result to `it`." ] @@ -1072,6 +1119,14 @@ _ | Just n <- readMaybe s -> return (SomeSat n) _ -> panic "REPL.Monad.getUserSatNum" [ "invalid satNum option" ]++checkTimeMeasurementPeriod :: Checker+checkTimeMeasurementPeriod (EnvNum n)+ | n >= 1 = noWarns Nothing+ | otherwise = noWarns $+ Just "timeMeasurementPeriod must be a positive integer"+checkTimeMeasurementPeriod _ = noWarns $+ Just "unable to parse value for timeMeasurementPeriod" -- Environment Utilities -------------------------------------------------------
src/Cryptol/Symbolic.hs view
@@ -349,7 +349,7 @@ in case res of Left _ -> mismatch -- different fields Right efs ->- let f = foldl (\x t -> ETApp x (tNumValTy t)) (EVar (ntName nt)) ts+ let f = foldl (\x t -> ETApp x (tNumValTy t)) (EVar (ntConName nt)) ts in EApp f (ERec efs) (FTRecord tfs, VarRecord vfs) ->
src/Cryptol/Symbolic/SBV.hs view
@@ -81,6 +81,7 @@ proverConfigs :: [(String, SBV.SMTConfig)] proverConfigs = [ ("cvc4" , SBV.cvc4 )+ , ("cvc5" , SBV.cvc5 ) , ("yices" , SBV.yices ) , ("z3" , SBV.z3 ) , ("boolector", SBV.boolector)@@ -90,6 +91,7 @@ , ("any" , SBV.defaultSMTCfg ) , ("sbv-cvc4" , SBV.cvc4 )+ , ("sbv-cvc5" , SBV.cvc5 ) , ("sbv-yices" , SBV.yices ) , ("sbv-z3" , SBV.z3 ) , ("sbv-boolector", SBV.boolector)@@ -298,9 +300,11 @@ ProverCommand -> M.ModuleT IO (Either String ([FinType], SBV.Symbolic SBV.SVal)) prepareQuery evo ProverCommand{..} =- do ds <- do (_mp, m) <- M.loadModuleFrom True (M.FromModule preludeReferenceName)+ do ds <- do (_mp, ent) <- M.loadModuleFrom True (M.FromModule preludeReferenceName)+ let m = tcTopEntityToModule ent+ let decls = mDecls m- let nms = fst <$> Map.toList (M.ifDecls (M.ifPublic (M.genIface m)))+ let nms = fst <$> Map.toList (M.ifDecls (M.ifDefines (M.genIface m))) let ds = Map.fromList [ (prelPrim (identText (M.nameIdent nm)), EWhere (EVar nm) decls) | nm <- nms ] pure ds @@ -409,7 +413,10 @@ -- otherwise something is wrong _ -> return $ ProverError (rshow results)-#if MIN_VERSION_sbv(8,8,0)+#if MIN_VERSION_sbv(10,0,0)+ where rshow | isSat = show . (SBV.AllSatResult False False False)+ -- sbv-10.0.0 removes the `allSatHasPrefixExistentials` field+#elif MIN_VERSION_sbv(8,8,0) where rshow | isSat = show . (SBV.AllSatResult False False False False) #else where rshow | isSat = show . SBV.AllSatResult . (False,False,False,)@@ -464,11 +471,19 @@ ProveQuery -> False SafetyQuery -> False SatQuery _ -> True++#if MIN_VERSION_sbv(10,0,0)+ generateSMTBenchmark+ | isSat = SBV.generateSMTBenchmarkSat+ | otherwise = SBV.generateSMTBenchmarkProof+#else+ generateSMTBenchmark = SBV.generateSMTBenchmark isSat+#endif evo <- liftIO (M.minpEvalOpts minp) prepareQuery evo pc >>= \case Left msg -> return (Left msg)- Right (_ts, q) -> Right <$> M.io (SBV.generateSMTBenchmark isSat q)+ Right (_ts, q) -> Right <$> M.io (generateSMTBenchmark q) protectStack :: (String -> M.ModuleCmd a) -> M.ModuleCmd a
src/Cryptol/Symbolic/What4.hs view
@@ -18,6 +18,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ViewPatterns #-} @@ -37,7 +38,7 @@ import Control.Monad.IO.Class import Control.Monad (when, foldM, forM_, void) import qualified Control.Exception as X-import System.IO (Handle)+import System.IO (Handle, IOMode(..), withFile) import Data.Time import Data.IORef import Data.List (intercalate, tails, inits)@@ -82,6 +83,7 @@ import What4.Solver import qualified What4.Solver.Boolector as W4 import qualified What4.Solver.CVC4 as W4+import qualified What4.Solver.CVC5 as W4 import qualified What4.Solver.ExternalABC as W4 import qualified What4.Solver.Yices as W4 import qualified What4.Solver.Z3 as W4@@ -160,6 +162,7 @@ proverConfigs :: [(String, W4ProverConfig)] proverConfigs = [ ("w4-cvc4" , W4ProverConfig cvc4OnlineAdapter)+ , ("w4-cvc5" , W4ProverConfig cvc5OnlineAdapter) , ("w4-yices" , W4ProverConfig yicesOnlineAdapter) , ("w4-z3" , W4ProverConfig z3OnlineAdapter) , ("w4-boolector" , W4ProverConfig boolectorOnlineAdapter)@@ -185,6 +188,11 @@ AnOnlineAdapter "CVC4" W4.cvc4Features W4.cvc4Options (Proxy :: Proxy (W4.Writer W4.CVC4)) +cvc5OnlineAdapter :: AnAdapter+cvc5OnlineAdapter =+ AnOnlineAdapter "CVC5" W4.cvc5Features W4.cvc5Options+ (Proxy :: Proxy (W4.Writer W4.CVC5))+ boolectorOnlineAdapter :: AnAdapter boolectorOnlineAdapter = AnOnlineAdapter "Boolector" W4.boolectorFeatures W4.boolectorOptions@@ -194,6 +202,7 @@ allSolvers = W4Portfolio $ z3OnlineAdapter :| [ cvc4OnlineAdapter+ , cvc5OnlineAdapter , boolectorOnlineAdapter , yicesOnlineAdapter , AnAdapter W4.externalABCAdapter@@ -333,9 +342,10 @@ do let lPutStrLn = M.withLogger logPutStrLn when pcVerbose (lPutStrLn "Simulating...") - ds <- do (_mp, m) <- M.loadModuleFrom True (M.FromModule preludeReferenceName)+ ds <- do (_mp, ent) <- M.loadModuleFrom True (M.FromModule preludeReferenceName)+ let m = tcTopEntityToModule ent let decls = mDecls m- let nms = fst <$> Map.toList (M.ifDecls (M.ifPublic (M.genIface m)))+ let nms = fst <$> Map.toList (M.ifDecls (M.ifDefines (M.genIface m))) let ds = Map.fromList [ (prelPrim (identText (M.nameIdent nm)), EWhere (EVar nm) decls) | nm <- nms ] pure ds @@ -373,7 +383,7 @@ ProverCommand -> M.ModuleCmd (Maybe String, ProverResult) -satProve solverCfg hashConsing warnUninterp ProverCommand {..} =+satProve solverCfg hashConsing warnUninterp pc@ProverCommand {..} = protectStack proverError \modIn -> M.runModuleM modIn do w4sym <- liftIO makeSym@@ -414,13 +424,13 @@ Right (ts,args,safety,query) -> case pcQueryType of ProveQuery ->- singleQuery sym solverCfg primMap logData ts args (Just safety) query+ singleQuery sym solverCfg pc primMap logData ts args (Just safety) query SafetyQuery ->- singleQuery sym solverCfg primMap logData ts args (Just safety) query+ singleQuery sym solverCfg pc primMap logData ts args (Just safety) query SatQuery num ->- multiSATQuery sym solverCfg primMap logData ts args query num+ multiSATQuery sym solverCfg pc primMap logData ts args query num printUninterpWarn :: Logger -> Set Text -> IO () printUninterpWarn lg uninterpWarns =@@ -477,6 +487,7 @@ sym ~ W4.ExprBuilder t CryptolState fm => What4 sym -> W4ProverConfig ->+ ProverCommand -> PrimMap -> W4.LogData -> [FinType] ->@@ -485,23 +496,24 @@ SatNum -> IO (Maybe String, ProverResult) -multiSATQuery sym solverCfg primMap logData ts args query (SomeSat n) | n <= 1 =- singleQuery sym solverCfg primMap logData ts args Nothing query+multiSATQuery sym solverCfg pc primMap logData ts args query (SomeSat n) | n <= 1 =+ singleQuery sym solverCfg pc primMap logData ts args Nothing query -multiSATQuery _sym W4OfflineConfig _primMap _logData _ts _args _query _satNum =+multiSATQuery _sym W4OfflineConfig _pc _primMap _logData _ts _args _query _satNum = fail "What4 offline solver cannot be used for multi-SAT queries" -multiSATQuery _sym (W4Portfolio _) _primMap _logData _ts _args _query _satNum =+multiSATQuery _sym (W4Portfolio _) _pc _primMap _logData _ts _args _query _satNum = fail "What4 portfolio solver cannot be used for multi-SAT queries" -multiSATQuery _sym (W4ProverConfig (AnAdapter adpt)) _primMap _logData _ts _args _query _satNum =+multiSATQuery _sym (W4ProverConfig (AnAdapter adpt)) _pc _primMap _logData _ts _args _query _satNum = fail ("Solver " ++ solver_adapter_name adpt ++ " does not support incremental solving and " ++ "cannot be used for multi-SAT queries.") multiSATQuery sym (W4ProverConfig (AnOnlineAdapter nm fs _opts (_ :: Proxy s)))- primMap _logData ts args query satNum0 =+ ProverCommand{..} primMap _logData ts args query satNum0 =+ withMaybeFile pcSmtFile WriteMode $ \smtFileHdl -> X.bracket- (W4.startSolverProcess fs Nothing (w4 sym))+ (W4.startSolverProcess fs smtFileHdl (w4 sym)) (void . W4.shutdownSolverProcess) (\ (proc :: W4.SolverProcess t s) -> do W4.assume (W4.solverConn proc) query@@ -627,6 +639,7 @@ sym ~ W4.ExprBuilder t CryptolState fm => What4 sym -> W4ProverConfig ->+ ProverCommand -> PrimMap -> W4.LogData -> [FinType] ->@@ -635,12 +648,12 @@ W4.Pred sym -> IO (Maybe String, ProverResult) -singleQuery _ W4OfflineConfig _primMap _logData _ts _args _msafe _query =+singleQuery _ W4OfflineConfig _pc _primMap _logData _ts _args _msafe _query = -- this shouldn't happen... fail "What4 offline solver cannot be used for direct queries" -singleQuery sym (W4Portfolio ps) primMap logData ts args msafe query =- do as <- mapM async [ singleQuery sym (W4ProverConfig p) primMap logData ts args msafe query+singleQuery sym (W4Portfolio ps) pc primMap logData ts args msafe query =+ do as <- mapM async [ singleQuery sym (W4ProverConfig p) pc primMap logData ts args msafe query | p <- NE.toList ps ] waitForResults [] as@@ -659,7 +672,7 @@ do forM_ others (\a -> X.throwTo (asyncThreadId a) ExitSuccess) return r -singleQuery sym (W4ProverConfig (AnAdapter adpt)) primMap logData ts args msafe query =+singleQuery sym (W4ProverConfig (AnAdapter adpt)) _pc primMap logData ts args msafe query = do pres <- W4.solver_adapter_check_sat adpt (w4 sym) logData [query] $ \res -> case res of W4.Unknown -> return (ProverError "Solver returned UNKNOWN")@@ -677,9 +690,10 @@ return (Just (W4.solver_adapter_name adpt), pres) singleQuery sym (W4ProverConfig (AnOnlineAdapter nm fs _opts (_ :: Proxy s)))- primMap _logData ts args msafe query =+ ProverCommand{..} primMap _logData ts args msafe query =+ withMaybeFile pcSmtFile WriteMode $ \smtFileHdl -> X.bracket- (W4.startSolverProcess fs Nothing (w4 sym))+ (W4.startSolverProcess fs smtFileHdl (w4 sym)) (void . W4.shutdownSolverProcess) (\ (proc :: W4.SolverProcess t s) -> do W4.assume (W4.solverConn proc) query@@ -698,6 +712,13 @@ Nothing -> return (Just nm, AllSatResult [ model ]) ) ++-- | Like 'withFile', but lifted to work over 'Maybe'.+withMaybeFile :: Maybe FilePath -> IOMode -> (Maybe Handle -> IO r) -> IO r+withMaybeFile mbFP mode action =+ case mbFP of+ Just fp -> withFile fp mode (action . Just)+ Nothing -> action Nothing computeModelPred :: sym ~ W4.ExprBuilder t CryptolState fm =>
src/Cryptol/Testing/Random.hs view
@@ -23,8 +23,10 @@ , TestResult(..) , isPass , returnTests+, returnTests' , exhaustiveTests , randomTests+, randomTests' ) where import qualified Control.Exception as X@@ -96,23 +98,32 @@ go _ (_ : _) = panic "Cryptol.Testing.Random" ["Too many arguments to function while generating tests"] go v [] = return v ---- | Return a collection of random tests. returnTests :: RandomGen g => g -- ^ The random generator state -> [Gen g Concrete] -- ^ Generators for the function arguments -> Value -- ^ The function itself -> Int -- ^ How many tests? -> IO [([Value], Value)] -- ^ A list of pairs of random arguments and computed outputs-returnTests g gens fun num = go gens g 0+ -- as well as the new state of the RNG+returnTests g gens fun num = fst <$> returnTests' g gens fun num++-- | Return a collection of random tests.+returnTests' :: RandomGen g+ => g -- ^ The random generator state+ -> [Gen g Concrete] -- ^ Generators for the function arguments+ -> Value -- ^ The function itself+ -> Int -- ^ How many tests?+ -> IO ([([Value], Value)], g) -- ^ A list of pairs of random arguments and computed outputs+ -- as well as the new state of the RNG+returnTests' g gens fun num = go gens g 0 where go args g0 n- | n >= num = return []+ | n >= num = return ([], g0) | otherwise = do let sz = toInteger (div (100 * (1 + n)) num) (inputs, output, g1) <- returnOneTest fun args sz g0- more <- go args g1 (n + 1)- return ((inputs, output) : more)+ (more, g2) <- go args g1 (n + 1)+ return ((inputs, output) : more, g2) {- | Given a (function) type, compute generators for the function's arguments. -}@@ -447,14 +458,23 @@ [Gen g Concrete] {- ^ input value generators -} -> g {- ^ Inital random generator -} -> m (TestResult, Integer)-randomTests ppProgress maxTests val gens = go 0+randomTests ppProgress maxTests val gens g = fst <$> randomTests' ppProgress maxTests val gens g++randomTests' :: (MonadIO m, RandomGen g) =>+ (Integer -> m ()) {- ^ progress callback -} ->+ Integer {- ^ Maximum number of tests to run -} ->+ Value {- ^ function under test -} ->+ [Gen g Concrete] {- ^ input value generators -} ->+ g {- ^ Inital random generator -} ->+ m ((TestResult, Integer), g)+randomTests' ppProgress maxTests val gens = go 0 where go !testNum g- | testNum >= maxTests = return (Pass, testNum)+ | testNum >= maxTests = return ((Pass, testNum), g) | otherwise = do ppProgress testNum let sz' = div (100 * (1 + testNum)) maxTests (res, g') <- liftIO (runOneTest val gens sz' g) case res of Pass -> go (testNum+1) g'- failure -> return (failure, testNum)+ failure -> return ((failure, testNum), g)
− src/Cryptol/Transform/AddModParams.hs
@@ -1,314 +0,0 @@--- | Transformed a parametrized module into an ordinary module--- where everything is parameterized by the module's parameters.--- Note that this reuses the names from the original parameterized module.-module Cryptol.Transform.AddModParams (addModParams) where--import Data.Map ( Map )-import qualified Data.Map as Map-import Data.Set ( Set )-import qualified Data.Set as Set-import Data.Either(partitionEithers)-import Data.List(find,sortBy)-import Data.Ord(comparing)--import Cryptol.TypeCheck.AST-import Cryptol.Parser.Position(thing)-import Cryptol.ModuleSystem.Name(toParamInstName,asParamName,nameIdent- ,paramModRecParam)-import Cryptol.Utils.Ident(paramInstModName)-import Cryptol.Utils.RecordMap(recordFromFields)--{--Note that we have to be careful when doing this transformation on-polyomorphic values. In particular,---Consider type parameters AS, with constraints CS, and value-parameters (xs : TS).-- f : {as} PS => t- f = f`{as} (<> ..)-- ~~>-- f : {AS ++ as} (CS ++ PS) => { TS } -> t- f = /\ (AS ++ as) ->- \\ (CS ++ PS) ->- \r -> f`{AS ++ as} (<> ...) r--The tricky bit is that we can't just replace `f` with-a new version of `f` with some arguments, instead ew have-to modify the whole instantiation of `f` : f`{as} (<>...)---}---addModParams :: Module -> Either [Name] Module-addModParams m =- case getParams m of- Left errs -> Left errs- Right ps ->- let toInst = Set.unions ( Map.keysSet (mTySyns m)- : Map.keysSet (mNewtypes m)- : map defs (mDecls m)- )- inp = (toInst, ps { pTypeConstraints = inst inp (pTypeConstraints ps) })-- in Right m { mName = paramInstModName (mName m)- , mTySyns = fixMap inp (mTySyns m)- , mNewtypes = fixMap inp (mNewtypes m)- , mDecls = fixUp inp (mDecls m)- , mParamTypes = Map.empty- , mParamConstraints = []- , mParamFuns = Map.empty- }--defs :: DeclGroup -> Set Name-defs dg =- case dg of- Recursive ds -> Set.fromList (map dName ds)- NonRecursive d -> Set.singleton (dName d)--fixUp :: (AddParams a, Inst a) => Inp -> a -> a-fixUp i = addParams (snd i) . inst i--fixMap :: (AddParams a, Inst a) => Inp -> Map Name a -> Map Name a-fixMap i m =- Map.fromList [ (toParamInstName x, fixUp i a) | (x,a) <- Map.toList m ]------------------------------------------------------------------------------------data Params = Params- { pTypes :: [TParam]- , pTypeConstraints :: [Prop]- , pFuns :: [(Name,Type)]- }---getParams :: Module -> Either [Name] Params-getParams m- | null errs =- let ps = Params { pTypes = map rnTP- $ sortBy (comparing mtpNumber)- $ Map.elems- $ mParamTypes m- , pTypeConstraints = map thing (mParamConstraints m)- , pFuns = oks- }- in Right ps- | otherwise = Left errs- where- (errs,oks) = partitionEithers (map checkFunP (Map.toList (mParamFuns m)))-- checkFunP (x,s) = case isMono (mvpType s) of- Just t -> Right (asParamName x, t)- Nothing -> Left x-- rnTP tp = mtpParam tp { mtpName = asParamName (mtpName tp) }------------------------------------------------------------------------------------class AddParams a where- addParams :: Params -> a -> a--instance AddParams a => AddParams [a] where- addParams ps = map (addParams ps)--instance AddParams Schema where- addParams ps s = s { sVars = pTypes ps ++ sVars s- , sProps = pTypeConstraints ps ++ sProps s- , sType = addParams ps (sType s)- }--instance AddParams Type where- addParams ps t- | null (pFuns ps) = t- | otherwise = tFun (paramRecTy ps) t---instance AddParams Expr where- addParams ps e = foldr ETAbs withProps (pTypes ps ++ as)- where (as,rest1) = splitWhile splitTAbs e- (bs,rest2) = splitWhile splitProofAbs rest1- withProps = foldr EProofAbs withArgs (pTypeConstraints ps ++ bs)- withArgs- | null (pFuns ps) = rest2- | otherwise = EAbs paramModRecParam (paramRecTy ps) rest2----instance AddParams DeclGroup where- addParams ps dg =- case dg of- Recursive ds -> Recursive (addParams ps ds)- NonRecursive d -> NonRecursive (addParams ps d)--instance AddParams Decl where- addParams ps d =- case dDefinition d of- DPrim -> d- DExpr e -> d { dSignature = addParams ps (dSignature d)- , dDefinition = DExpr (addParams ps e)- , dName = toParamInstName (dName d)- }--instance AddParams TySyn where- addParams ps ts = ts { tsParams = pTypes ps ++ tsParams ts- , tsConstraints = pTypeConstraints ps ++ tsConstraints ts- -- do we need these here ^ ?- , tsName = toParamInstName (tsName ts)- }--instance AddParams Newtype where- addParams ps nt = nt { ntParams = pTypes ps ++ ntParams nt- , ntConstraints = pTypeConstraints ps ++ ntConstraints nt- , ntName = toParamInstName (ntName nt)- }-------------------------------------------------------------------------------------------- | Adjust uses of names to account for the new parameters.--- Assumes unique names---no capture or shadowing.-class Inst a where- inst :: Inp -> a -> a---- | Set of top-level names which need to be instantiate, and module parameters.-type Inp = (Set Name, Params)---paramRecTy :: Params -> Type-paramRecTy ps = tRec (recordFromFields [ (nameIdent x, t) | (x,t) <- pFuns ps ])---nameInst :: Inp -> Name -> [Type] -> Int -> Expr-nameInst (_,ps) x ts prfs- | null (pFuns ps) = withProofs- | otherwise = EApp withProofs (EVar paramModRecParam)- where- withProofs = iterate EProofApp withTys !!- (length (pTypeConstraints ps) + prfs)-- withTys = foldl ETApp (EVar (toParamInstName x))- (map (TVar . tpVar) (pTypes ps) ++ ts)----- | Extra parameters to dd when instantiating a type-instTyParams :: Inp -> [Type]-instTyParams (_,ps) = map (TVar . tpVar) (pTypes ps)---needsInst :: Inp -> Name -> Bool-needsInst (xs,_) x = Set.member x xs--isVParam :: Inp -> Name -> Bool-isVParam (_,ps) x = x `elem` map fst (pFuns ps)--isTParam :: Inp -> TVar -> Maybe TParam-isTParam (_,ps) x =- case x of- TVBound tp -> find thisName (pTypes ps)- where thisName y = tpName tp == tpName y- _ -> Nothing---instance Inst a => Inst [a] where- inst ps = map (inst ps)--instance Inst Expr where- inst ps expr =- case expr of- EVar x- | needsInst ps x -> nameInst ps x [] 0- | isVParam ps x ->- let sh = map (nameIdent . fst) (pFuns (snd ps))- in ESel (EVar paramModRecParam) (RecordSel (nameIdent x) (Just sh))- | otherwise -> EVar x-- ELocated r t -> ELocated r (inst ps t)- EList es t -> EList (inst ps es) (inst ps t)- ETuple es -> ETuple (inst ps es)- ERec fs -> ERec (fmap (inst ps) fs)- ESel e s -> ESel (inst ps e) s- ESet ty e s v -> ESet (inst ps ty) (inst ps e) s (inst ps v)-- EIf e1 e2 e3 -> EIf (inst ps e1) (inst ps e2) (inst ps e3)- EComp t1 t2 e ms -> EComp (inst ps t1) (inst ps t2)- (inst ps e) (inst ps ms)-- ETAbs x e -> ETAbs x (inst ps e)- ETApp e1 t ->- case splitExprInst expr of- (EVar x, ts, prfs) | needsInst ps x -> nameInst ps x ts prfs- _ -> ETApp (inst ps e1) t-- EApp e1 e2 -> EApp (inst ps e1) (inst ps e2)- EAbs x t e -> EAbs x (inst ps t) (inst ps e)-- EProofAbs p e -> EProofAbs (inst ps p) (inst ps e)- EProofApp e1 ->- case splitExprInst expr of- (EVar x, ts, prfs) | needsInst ps x -> nameInst ps x ts prfs- _ -> EProofApp (inst ps e1)-- EWhere e dgs -> EWhere (inst ps e) (inst ps dgs)---instance Inst Match where- inst ps m =- case m of- From x t1 t2 e -> From x (inst ps t1) (inst ps t2) (inst ps e)- Let d -> Let (inst ps d)--instance Inst DeclGroup where- inst ps dg =- case dg of- Recursive ds -> Recursive (inst ps ds)- NonRecursive d -> NonRecursive (inst ps d)--instance Inst Decl where- inst ps d = d { dDefinition = inst ps (dDefinition d) }--instance Inst DeclDef where- inst ps d =- case d of- DPrim -> DPrim- DExpr e -> DExpr (inst ps e)--instance Inst Type where- inst ps ty =- case ty of- TUser x ts t- | needsInst ps x -> TUser x (instTyParams ps ++ ts1) t1- | otherwise -> TUser x ts1 t1- where ts1 = inst ps ts- t1 = inst ps t-- TNewtype nt ts- | needsInst ps (ntName nt) -> TNewtype (inst ps nt) (instTyParams ps ++ ts1)- | otherwise -> TNewtype nt ts1- where ts1 = inst ps ts-- TCon tc ts -> TCon tc (inst ps ts)-- TVar x | Just x' <- isTParam ps x -> TVar (TVBound x')- | otherwise -> ty-- TRec xs -> TRec (fmap (inst ps) xs)--instance Inst TySyn where- inst ps ts = ts { tsConstraints = inst ps (tsConstraints ts)- , tsDef = inst ps (tsDef ts)- }--instance Inst Newtype where- inst ps nt = nt { ntConstraints = inst ps (ntConstraints nt)- , ntFields = fmap (inst ps) (ntFields nt)- }--
src/Cryptol/Transform/MonoValues.hs view
@@ -201,7 +201,9 @@ EWhere e dgs -> EWhere <$> go e <*> inLocal (mapM (rewDeclGroup rews) dgs) + EPropGuards guards ty -> EPropGuards <$> (\(props, e) -> (,) <$> pure props <*> go e) `traverse` guards <*> pure ty + rewM :: RewMap -> Match -> M Match rewM rews ma = case ma of@@ -216,8 +218,9 @@ return d { dDefinition = e } rewDef :: RewMap -> DeclDef -> M DeclDef-rewDef rews (DExpr e) = DExpr <$> rewE rews e-rewDef _ DPrim = return DPrim+rewDef rews (DExpr e) = DExpr <$> rewE rews e+rewDef _ DPrim = return DPrim+rewDef _ (DForeign t) = return $ DForeign t rewDeclGroup :: RewMap -> DeclGroup -> M DeclGroup rewDeclGroup rews dg =@@ -237,11 +240,12 @@ consider d = case dDefinition d of- DPrim -> Left d- DExpr e -> let (tps,props,e') = splitTParams e- in if not (null tps) && notFun e'- then Right (d, tps, props, e')- else Left d+ DPrim -> Left d+ DForeign _ -> Left d+ DExpr e -> let (tps,props,e') = splitTParams e+ in if not (null tps) && notFun e'+ then Right (d, tps, props, e')+ else Left d rewSame ds = do new <- forM (NE.toList ds) $ \(d,_,_,e) ->
src/Cryptol/Transform/Specialize.hs view
@@ -19,13 +19,18 @@ import qualified Cryptol.ModuleSystem.Env as M import qualified Cryptol.ModuleSystem.Monad as M import Cryptol.ModuleSystem.Name+import Cryptol.Utils.Ident(OrigName(..))+import Cryptol.Eval (checkProp) import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (catMaybes)+import qualified Data.List as List import MonadLib hiding (mapM)+import Cryptol.ModuleSystem.Base (getPrimMap) + -- Specializer Monad ----------------------------------------------------------- -- | A 'Name' should have an entry in the 'SpecCache' iff it is@@ -102,7 +107,17 @@ EProofAbs p e -> EProofAbs p <$> specializeExpr e EProofApp {} -> specializeConst expr EWhere e dgs -> specializeEWhere e dgs+ -- The type should be monomorphic, and the guarded expressions should+ -- already be normalized, so we just need to choose the first expression+ -- that's true.+ EPropGuards guards ty -> + case List.find (all checkProp . fst) guards of+ Just (_, e) -> specializeExpr e+ Nothing -> do+ pm <- liftSpecT getPrimMap+ pure $ eError pm ty "no constraint guard was satisfied" + specializeMatch :: Match -> SpecM Match specializeMatch (From qn l t e) = From qn l t <$> specializeExpr e specializeMatch (Let decl)@@ -187,9 +202,10 @@ sig' <- instantiateSchema ts n (dSignature decl) modifySpecCache (Map.adjust (fmap (insertTM ts (qname', Nothing))) qname) rhs' <- case dDefinition decl of- DExpr e -> do e' <- specializeExpr =<< instantiateExpr ts n e- return (DExpr e')- DPrim -> return DPrim+ DExpr e -> do e' <- specializeExpr =<< instantiateExpr ts n e+ return (DExpr e')+ DPrim -> return DPrim+ DForeign t -> return $ DForeign t let decl' = decl { dName = qname', dSignature = sig', dDefinition = rhs' } modifySpecCache (Map.adjust (fmap (insertTM ts (qname', Just decl'))) qname) return (EVar qname')@@ -245,8 +261,8 @@ freshName :: Name -> [Type] -> SpecM Name freshName n _ = case nameInfo n of- Declared m s -> liftSupply (mkDeclared ns m s ident fx loc)- Parameter -> liftSupply (mkParameter ns ident loc)+ GlobalName s og -> liftSupply (mkDeclared ns (ogModule og) s ident fx loc)+ LocalName {} -> liftSupply (mkLocal ns ident loc) where ns = nameNamespace n fx = nameFixity n
src/Cryptol/TypeCheck.hs view
@@ -9,7 +9,6 @@ module Cryptol.TypeCheck ( tcModule- , tcModuleInst , tcExpr , tcDecls , InferInput(..)@@ -28,12 +27,10 @@ , ppNamedError ) where -import Data.IORef(IORef,modifyIORef') import Data.Map(Map) import Cryptol.ModuleSystem.Name (liftSupply,mkDeclared,NameSource(..),ModPath(..))-import Cryptol.ModuleSystem.NamingEnv(NamingEnv,namingEnvRename) import qualified Cryptol.Parser.AST as P import Cryptol.Parser.Position(Range,emptyRange) import Cryptol.TypeCheck.AST@@ -46,14 +43,10 @@ , nameSeeds , lookupVar , newLocalScope, endLocalScope- , newModuleScope, addParamType, addParameterConstraints- , endModuleInstance- , io )-import Cryptol.TypeCheck.Infer (inferModule, inferBinds, checkTopDecls)+import Cryptol.TypeCheck.Infer (inferTopModule, inferBinds, checkTopDecls) import Cryptol.TypeCheck.InferTypes(VarType(..), SolverConfig(..), defaultSolverConfig) import Cryptol.TypeCheck.Solve(proveModuleTopLevel)-import Cryptol.TypeCheck.CheckModuleInstance(checkModuleInstance) -- import Cryptol.TypeCheck.Monad(withParamType,withParameterConstraints) import Cryptol.TypeCheck.PP(WithNames(..),NameMap) import Cryptol.Utils.Ident (exprModName,packIdent,Namespace(..))@@ -62,27 +55,8 @@ -tcModule :: P.Module Name -> InferInput -> IO (InferOutput Module)-tcModule m inp = runInferM inp (inferModule m)---- | Check a module instantiation, assuming that the functor has already--- been checked.--- XXX: This will change-tcModuleInst :: IORef NamingEnv {- ^ renaming environment of functor -} ->- Module {- ^ functor -} ->- P.Module Name {- ^ params -} ->- InferInput {- ^ TC settings -} ->- IO (InferOutput Module) {- ^ new version of instance -}-tcModuleInst renThis func m inp = runInferM inp $- do x <- inferModule m- newModuleScope (mName func) [] mempty- mapM_ addParamType (mParamTypes x)- addParameterConstraints (mParamConstraints x)- (ren,y) <- checkModuleInstance func x- io $ modifyIORef' renThis (namingEnvRename ren)- proveModuleTopLevel- endModuleInstance- pure y+tcModule :: P.Module Name -> InferInput -> IO (InferOutput TCTopEntity)+tcModule m inp = runInferM inp (inferTopModule m) tcExpr :: P.Expr Name -> InferInput -> IO (InferOutput (Expr,Schema)) tcExpr e0 inp = runInferM inp
src/Cryptol/TypeCheck/AST.hs view
@@ -13,12 +13,14 @@ {-# LANGUAGE FlexibleInstances, FlexibleContexts #-} {-# LANGUAGE DeriveAnyClass, DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE ViewPatterns #-} module Cryptol.TypeCheck.AST ( module Cryptol.TypeCheck.AST , Name() , TFun(..) , Selector(..)- , Import, ImportG(..)+ , Import, ImportG(..), ImpName(..) , ImportSpec(..) , ExportType(..) , ExportSpec(..), isExportedBind, isExportedType, isExported@@ -28,6 +30,10 @@ , module Cryptol.TypeCheck.Type ) where +import Data.Maybe(mapMaybe)++import Cryptol.Utils.Panic(panic)+import Cryptol.Utils.Ident (Ident,isInfixIdent,ModName,PrimIdent,prelPrim) import Cryptol.Parser.Position(Located,Range,HasLoc(..)) import Cryptol.ModuleSystem.Name import Cryptol.ModuleSystem.Interface@@ -36,72 +42,124 @@ import Cryptol.Parser.AST ( Selector(..),Pragma(..) , Import , ImportG(..), ImportSpec(..), ExportType(..)- , Fixity(..))-import Cryptol.Utils.Ident (Ident,isInfixIdent,ModName,PrimIdent,prelPrim)+ , Fixity(..)+ , ImpName(..)+ ) import Cryptol.Utils.RecordMap+import Cryptol.TypeCheck.FFI.FFIType import Cryptol.TypeCheck.PP import Cryptol.TypeCheck.Type import GHC.Generics (Generic) import Control.DeepSeq ++import Data.Set (Set) import Data.Map (Map) import qualified Data.Map as Map import qualified Data.IntMap as IntMap import Data.Text (Text) +data TCTopEntity =+ TCTopModule (ModuleG ModName)+ | TCTopSignature ModName ModParamNames+ deriving (Show, Generic, NFData)++tcTopEntitytName :: TCTopEntity -> ModName+tcTopEntitytName ent =+ case ent of+ TCTopModule m -> mName m+ TCTopSignature m _ -> m++-- | Panics if the entity is not a module+tcTopEntityToModule :: TCTopEntity -> Module+tcTopEntityToModule ent =+ case ent of+ TCTopModule m -> m+ TCTopSignature {} -> panic "tcTopEntityToModule" [ "Not a module" ]++ -- | A Cryptol module. data ModuleG mname = Module { mName :: !mname+ , mDoc :: !(Maybe Text) , mExports :: ExportSpec Name- , mImports :: [Import] - {-| Interfaces of submodules, including functors.- This is only the directly nested modules.- Info about more nested modules is in the- corresponding interface. -}- , mSubModules :: Map Name (IfaceG Name)-- -- params, if functor+ -- Functors: , mParamTypes :: Map Name ModTParam- , mParamConstraints :: [Located Prop] , mParamFuns :: Map Name ModVParam+ , mParamConstraints :: [Located Prop] + , mParams :: FunctorParams+ -- ^ Parameters grouped by "import". - -- Declarations, including everything from non-functor- -- submodules+ , mFunctors :: Map Name (ModuleG Name)+ -- ^ Functors directly nested in this module.+ -- Things further nested are in the modules in the+ -- elements of the map.+++ , mNested :: !(Set Name)+ -- ^ Submodules, functors, and interfaces nested directly+ -- in this module++ -- These have everything from this module and all submodules , mTySyns :: Map Name TySyn , mNewtypes :: Map Name Newtype , mPrimTypes :: Map Name AbstractType , mDecls :: [DeclGroup]- , mFunctors :: Map Name (ModuleG Name)+ , mSubmodules :: Map Name (IfaceNames Name)+ , mSignatures :: !(Map Name ModParamNames) } deriving (Show, Generic, NFData) emptyModule :: mname -> ModuleG mname emptyModule nm = Module { mName = nm+ , mDoc = Nothing , mExports = mempty- , mImports = []- , mSubModules = mempty + , mParams = mempty , mParamTypes = mempty , mParamConstraints = mempty , mParamFuns = mempty + , mNested = mempty+ , mTySyns = mempty , mNewtypes = mempty , mPrimTypes = mempty , mDecls = mempty , mFunctors = mempty+ , mSubmodules = mempty+ , mSignatures = mempty } +-- | Find all the foreign declarations in the module and return their names and FFIFunTypes.+findForeignDecls :: ModuleG mname -> [(Name, FFIFunType)]+findForeignDecls = mapMaybe getForeign . mDecls+ where getForeign (NonRecursive Decl { dName, dDefinition = DForeign ffiType })+ = Just (dName, ffiType)+ -- Recursive DeclGroups can't have foreign decls+ getForeign _ = Nothing++-- | Find all the foreign declarations that are in functors.+-- This is used to report an error+findForeignDeclsInFunctors :: ModuleG mname -> [Name]+findForeignDeclsInFunctors = concatMap fromM . Map.elems . mFunctors+ where+ fromM m = map fst (findForeignDecls m) ++ findForeignDeclsInFunctors m++++ type Module = ModuleG ModName -- | Is this a parameterized module? isParametrizedModule :: ModuleG mname -> Bool-isParametrizedModule m = not (null (mParamTypes m) &&+isParametrizedModule m = not (null (mParams m) &&+ null (mParamTypes m) && null (mParamConstraints m) && null (mParamFuns m)) @@ -149,6 +207,8 @@ | EWhere Expr [DeclGroup] + | EPropGuards [([Prop], Expr)] Type+ deriving (Show, Generic, NFData) @@ -178,6 +238,7 @@ } deriving (Generic, NFData, Show) data DeclDef = DPrim+ | DForeign FFIFunType | DExpr Expr deriving (Show, Generic, NFData) @@ -202,7 +263,14 @@ where v = fromEnum c w = 8 :: Int +instance PP TCTopEntity where+ ppPrec _ te =+ case te of+ TCTopModule m -> pp m+ TCTopSignature x p ->+ ("interface" <+> pp x <+> "where") $$ nest 2 (pp p) + instance PP (WithNames Expr) where ppPrec prec (WithNames expr nm) = case expr of@@ -266,6 +334,12 @@ , hang "where" 2 (vcat (map ppW ds)) ] + EPropGuards guards _ -> + parens (text "propguards" <+> vsep (ppGuard <$> guards))+ where ppGuard (props, e) = indent 1+ $ pipe <+> commaSep (ppW <$> props)+ <+> text "=>" <+> ppW e+ where ppW x = ppWithNames nm x ppWP x = ppWithNamesPrec nm x@@ -296,24 +370,38 @@ Just (x,e1) -> let (xs,e2) = splitWhile f e1 in (x:xs,e2) +splitLoc :: Expr -> Maybe (Range, Expr)+splitLoc expr =+ case expr of+ ELocated r e -> Just (r,e)+ _ -> Nothing++-- | Remove outermost locations+dropLocs :: Expr -> Expr+dropLocs = snd . splitWhile splitLoc+ splitAbs :: Expr -> Maybe ((Name,Type), Expr)-splitAbs (EAbs x t e) = Just ((x,t), e)-splitAbs _ = Nothing+splitAbs (dropLocs -> EAbs x t e) = Just ((x,t), e)+splitAbs _ = Nothing +splitApp :: Expr -> Maybe (Expr,Expr)+splitApp (dropLocs -> EApp f a) = Just (a, f)+splitApp _ = Nothing+ splitTAbs :: Expr -> Maybe (TParam, Expr)-splitTAbs (ETAbs t e) = Just (t, e)-splitTAbs _ = Nothing+splitTAbs (dropLocs -> ETAbs t e) = Just (t, e)+splitTAbs _ = Nothing splitProofAbs :: Expr -> Maybe (Prop, Expr)-splitProofAbs (EProofAbs p e) = Just (p,e)-splitProofAbs _ = Nothing+splitProofAbs (dropLocs -> EProofAbs p e) = Just (p,e)+splitProofAbs _ = Nothing splitTApp :: Expr -> Maybe (Type,Expr)-splitTApp (ETApp e t) = Just (t, e)-splitTApp _ = Nothing+splitTApp (dropLocs -> ETApp e t) = Just (t, e)+splitTApp _ = Nothing splitProofApp :: Expr -> Maybe ((), Expr)-splitProofApp (EProofApp e) = Just ((), e)+splitProofApp (dropLocs -> EProofApp e) = Just ((), e) splitProofApp _ = Nothing -- | Deconstruct an expression, typically polymorphic, into@@ -368,8 +456,9 @@ ++ [ nest 2 (sep [pp dName <+> text "=", ppWithNames nm dDefinition]) ] instance PP (WithNames DeclDef) where- ppPrec _ (WithNames DPrim _) = text "<primitive>"- ppPrec _ (WithNames (DExpr e) nm) = ppWithNames nm e+ ppPrec _ (WithNames DPrim _) = text "<primitive>"+ ppPrec _ (WithNames (DForeign _) _) = text "<foreign>"+ ppPrec _ (WithNames (DExpr e) nm) = ppWithNames nm e instance PP Decl where ppPrec = ppWithNamesPrec IntMap.empty@@ -379,10 +468,21 @@ instance PP n => PP (WithNames (ModuleG n)) where ppPrec _ (WithNames Module { .. } nm) =- text "module" <+> pp mName $$- -- XXX: Print exports?- vcat (map pp mImports) $$- -- XXX: Print tysyns- -- XXX: Print abstarct types/functions- vcat (map (ppWithNames (addTNames mps nm)) mDecls)+ vcat [ text "module" <+> pp mName+ -- XXX: Print exports?+ , vcat (map pp' (Map.elems mTySyns))+ -- XXX: Print abstarct types/functions+ , vcat (map pp' mDecls)++ , vcat (map pp (Map.elems mFunctors))+ ] where mps = map mtpParam (Map.elems mParamTypes)+ pp' :: PP (WithNames a) => a -> Doc+ pp' = ppWithNames (addTNames mps nm)++instance PP (WithNames TCTopEntity) where+ ppPrec _ (WithNames ent nm) =+ case ent of+ TCTopModule m -> ppWithNames nm m+ TCTopSignature n ps ->+ hang ("interface module" <+> pp n <+> "where") 2 (pp ps)
− src/Cryptol/TypeCheck/CheckModuleInstance.hs
@@ -1,201 +0,0 @@-{-# Language OverloadedStrings #-}--- See Note [-Wincomplete-uni-patterns and irrefutable patterns] in Cryptol.TypeCheck.TypePat-{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}-module Cryptol.TypeCheck.CheckModuleInstance (checkModuleInstance) where--import Data.Map ( Map )-import qualified Data.Map as Map-import Control.Monad(unless)--import Cryptol.Parser.Position(Located(..))-import qualified Cryptol.Parser.AST as P-import Cryptol.ModuleSystem.Name (nameIdent, nameLoc)-import Cryptol.ModuleSystem.InstantiateModule(instantiateModule)-import Cryptol.TypeCheck.AST-import Cryptol.TypeCheck.Monad-import Cryptol.TypeCheck.Infer-import Cryptol.TypeCheck.Subst-import Cryptol.TypeCheck.Error-import Cryptol.Utils.Panic----- | Check that the instance provides what the functor needs.-checkModuleInstance :: Module {- ^ type-checked functor -} ->- Module {- ^ type-checked instance -} ->- InferM (Name->Name,Module)- -- ^ Renaming,Instantiated module-checkModuleInstance func inst- | not (null (mSubModules func) && null (mSubModules inst)) =- do recordError $ TemporaryError- "Cannot combine nested modules with old-style parameterized modules"- pure (id,func) -- doesn't matter?- | otherwise =- do tMap <- checkTyParams func inst- vMap <- checkValParams func tMap inst- (ren, ctrs, m) <- instantiateModule func (mName inst) tMap vMap- let toG p = Goal { goal = thing p- , goalRange = srcRange p- , goalSource = CtModuleInstance (mName inst)- }- addGoals (map toG ctrs)- return ( ren- , Module { mName = mName m- , mExports = mExports m- , mImports = mImports inst ++ mImports m- -- Note that this is just here to record- -- the full dependencies, the actual imports- -- might be ambiguous, but that shouldn't- -- matters as names have been already resolved- , mTySyns = Map.union (mTySyns inst) (mTySyns m)- , mNewtypes = Map.union (mNewtypes inst) (mNewtypes m)- , mPrimTypes = Map.union (mPrimTypes inst) (mPrimTypes m)- , mParamTypes = mParamTypes inst- , mParamConstraints = mParamConstraints inst- , mParamFuns = mParamFuns inst- , mDecls = mDecls inst ++ mDecls m-- , mSubModules = mempty- , mFunctors = mempty- }- )---- | Check that the type parameters of the functors all have appropriate--- definitions.-checkTyParams :: Module -> Module -> InferM (Map TParam Type)-checkTyParams func inst =- Map.fromList <$> mapM checkTParamDefined (Map.elems (mParamTypes func))-- where- -- Maps to lookup things by identifier (i.e., lexical name)- -- rather than using the name unique.- identMap f m = Map.fromList [ (f x, ts) | (x,ts) <- Map.toList m ]- tySyns = identMap nameIdent (mTySyns inst)- newTys = identMap nameIdent (mNewtypes inst)- tParams = Map.fromList [ (tpId x, x) | x0 <- Map.elems (mParamTypes inst)- , let x = mtpParam x0 ]-- tpName' x = case tpName x of- Just n -> n- Nothing -> panic "inferModuleInstance.tpId" ["Missing name"]-- tpId = nameIdent . tpName'-- -- Find a definition for a given type parameter- checkTParamDefined tp0 =- let tp = mtpParam tp0- x = tpId tp- in case Map.lookup x tySyns of- Just ts -> checkTySynDef tp ts- Nothing ->- case Map.lookup x newTys of- Just nt -> checkNewTyDef tp nt- Nothing ->- case Map.lookup x tParams of- Just tp1 -> checkTP tp tp1- Nothing ->- do let x' = Located { thing = x,- srcRange = nameLoc (tpName' tp) }- recordError (MissingModTParam x')- return (tp, TVar (TVBound tp)) -- hm, maybe just stop!-- -- Check that a type parameter defined as a type synonym is OK- checkTySynDef tp ts =- do let k1 = kindOf tp- k2 = kindOf ts- unless (k1 == k2) (recordError (KindMismatch Nothing k1 k2))-- let nm = tsName ts- src = CtPartialTypeFun nm- mapM_ (newGoal src) (tsConstraints ts)-- return (tp, TUser nm [] (tsDef ts))-- -- Check that a type parameter defined a newtype is OK- -- This one is a bit weird: since the newtype is deinfed in the- -- instantiation, it will not be exported, and so won't be usable- -- in type signatures, directly. This could be worked around- -- if the parametrized module explictly exported a parameter via- -- a type synonym like this: `type T = p`, where `p` is one of- -- the parametersm and the declartion for `T` is public.- checkNewTyDef tp nt =- do let k1 = kindOf tp- k2 = kindOf nt- unless (k1 == k2) (recordError (KindMismatch Nothing k1 k2))-- let nm = ntName nt- src = CtPartialTypeFun nm- mapM_ (newGoal src) (ntConstraints nt)-- return (tp, TNewtype nt [])-- -- Check that a type parameter defined as another type parameter is OK- checkTP tp tp1 =- do let k1 = kindOf tp- k2 = kindOf tp1- unless (k1 == k2) (recordError (KindMismatch Nothing k1 k2))-- return (tp, TVar (TVBound tp1))-----checkValParams :: Module {- ^ Parameterized module -} ->- Map TParam Type {- ^ Type instantiations -} ->- Module {- ^ Instantiation module -} ->- InferM (Map Name Expr)- -- ^ Definitions for the parameters-checkValParams func tMap inst =- Map.fromList <$> mapM checkParam (Map.elems (mParamFuns func))- where- valMap = Map.fromList (defByParam ++ defByDef)-- defByDef = [ (nameIdent (dName d), (dName d, dSignature d))- | dg <- mDecls inst, d <- groupDecls dg ]-- defByParam = [ (nameIdent x, (x, mvpType s)) |- (x,s) <- Map.toList (mParamFuns inst) ]-- su = listParamSubst (Map.toList tMap)-- checkParam pr =- let x = mvpName pr- sP = mvpType pr- in- case Map.lookup (nameIdent x) valMap of- Just (n,sD) -> do e <- makeValParamDef n sD (apSubst su sP)- return (x,e)- Nothing -> do recordError (MissingModVParam- Located { thing = nameIdent x- , srcRange = nameLoc x })- return (x, panic "checkValParams" ["Should not use this"])------ | Given a parameter definition, compute an appropriate instantiation--- that will match the actual schema for the parameter.-makeValParamDef :: Name {- ^ Definition of parameter -} ->- Schema {- ^ Schema for parameter definition -} ->- Schema {- ^ Schema for parameter -} ->- InferM Expr {- ^ Expression to use for param definition -}--makeValParamDef x sDef pDef =- withVar x sDef $ do ~(DExpr e) <- dDefinition <$> checkSigB bnd (pDef,[])- return e- where- bnd = P.Bind { P.bName = loc x- , P.bParams = []- , P.bDef = loc (P.DExpr (P.EVar x))-- -- unused- , P.bSignature = Nothing- , P.bInfix = False- , P.bFixity = Nothing- , P.bPragmas = []- , P.bMono = False- , P.bDoc = Nothing- , P.bExport = Public- }- loc a = P.Located { P.srcRange = nameLoc x, P.thing = a }---
src/Cryptol/TypeCheck/Default.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE Safe #-}+ module Cryptol.TypeCheck.Default where import qualified Data.Set as Set
src/Cryptol/TypeCheck/Error.hs view
@@ -12,15 +12,16 @@ import Data.List((\\),sortBy,groupBy,partition) import Data.Function(on) +import Cryptol.Utils.Ident(Ident,Namespace(..)) import qualified Cryptol.Parser.AST as P-import Cryptol.Parser.Position(Located(..), Range(..))+import Cryptol.Parser.Position(Located(..), Range(..), rangeWithin) import Cryptol.TypeCheck.PP import Cryptol.TypeCheck.Type import Cryptol.TypeCheck.InferTypes import Cryptol.TypeCheck.Subst import Cryptol.TypeCheck.Unify(Path,isRootPath)+import Cryptol.TypeCheck.FFI.Error import Cryptol.ModuleSystem.Name(Name)-import Cryptol.Utils.Ident(Ident) import Cryptol.Utils.RecordMap cleanupErrors :: [(Range,Error)] -> [(Range,Error)]@@ -56,6 +57,8 @@ -- | Should the first error suppress the next one. subsumes :: (Range,Error) -> (Range,Error) -> Bool subsumes (_,NotForAll _ _ x _) (_,NotForAll _ _ y _) = x == y+subsumes (r1,UnexpectedTypeWildCard) (r2,UnsupportedFFIType{}) =+ r1 `rangeWithin` r2 subsumes (r1,KindMismatch {}) (r2,err) = case err of KindMismatch {} -> r1 == r2@@ -65,6 +68,7 @@ data Warning = DefaultingKind (P.TParam Name) P.Kind | DefaultingWildType P.Kind | DefaultingTo !TVarInfo Type+ | NonExhaustivePropGuards Name deriving (Show, Generic, NFData) -- | Various errors that might happen during type checking/inference@@ -90,6 +94,10 @@ | TypeMismatch TypeSource Path Type Type -- ^ Expected type, inferred type + | SchemaMismatch Ident Schema Schema+ -- ^ Name of module parameter, expected scehema, actual schema.+ -- This may happen when instantiating modules.+ | RecursiveType TypeSource Path Type Type -- ^ Unification results in a recursive type @@ -142,7 +150,28 @@ | TypeShadowing String Name String | MissingModTParam (Located Ident) | MissingModVParam (Located Ident)+ | MissingModParam Ident + | FunctorInstanceMissingArgument Ident+ | FunctorInstanceBadArgument Ident+ | FunctorInstanceMissingName Namespace Ident+ | FunctorInstanceBadBacktick BadBacktickInstance++ | UnsupportedFFIKind TypeSource TParam Kind+ -- ^ Kind is not supported for FFI+ | UnsupportedFFIType TypeSource FFITypeError+ -- ^ Type is not supported for FFI++ | NestedConstraintGuard Ident+ -- ^ Constraint guards may only apper at the top-level++ | DeclarationRequiresSignatureCtrGrd Ident+ -- ^ All declarataions in a recursive group involving+ -- constraint guards should have signatures++ | InvalidConstraintGuard Prop+ -- ^ The given constraint may not be used as a constraint guard+ | TemporaryError Doc -- ^ This is for errors that don't fit other cateogories. -- We should not use it much, and is generally to be used@@ -150,6 +179,15 @@ -- implementation. deriving (Show, Generic, NFData) +data BadBacktickInstance =+ BIPolymorphicArgument Ident Ident+ | BINested [(BIWhat, Name)]+ | BIMultipleParams Ident+ deriving (Show, Generic, NFData)++data BIWhat = BIFunctor | BIInterface | BIPrimitive | BIForeign | BIAbstractType+ deriving (Show, Generic, NFData)+ -- | When we have multiple errors on the same location, we show only the -- ones with the has highest rating according to this function. errorImportance :: Error -> Int@@ -159,10 +197,17 @@ TemporaryError {} -> 11 -- show these as usually means the user used something that doesn't work + FunctorInstanceMissingArgument {} -> 10+ MissingModParam {} -> 10+ FunctorInstanceBadArgument {} -> 10+ FunctorInstanceMissingName {} -> 9+ FunctorInstanceBadBacktick {} -> 9 + KindMismatch {} -> 10 TyVarWithParams {} -> 9 TypeMismatch {} -> 8+ SchemaMismatch {} -> 7 RecursiveType {} -> 7 NotForAll {} -> 6 TypeVariableEscaped {} -> 5@@ -199,7 +244,13 @@ AmbiguousSize {} -> 2 + UnsupportedFFIKind {} -> 10+ UnsupportedFFIType {} -> 7+ -- less than UnexpectedTypeWildCard + NestedConstraintGuard {} -> 10+ DeclarationRequiresSignatureCtrGrd {} -> 9+ InvalidConstraintGuard {} -> 5 instance TVars Warning where@@ -208,6 +259,7 @@ DefaultingKind {} -> warn DefaultingWildType {} -> warn DefaultingTo d ty -> DefaultingTo d $! (apSubst su ty)+ NonExhaustivePropGuards {} -> warn instance FVS Warning where fvs warn =@@ -215,6 +267,7 @@ DefaultingKind {} -> Set.empty DefaultingWildType {} -> Set.empty DefaultingTo _ ty -> fvs ty+ NonExhaustivePropGuards {} -> Set.empty instance TVars Error where apSubst su err =@@ -225,6 +278,8 @@ TooManyTySynParams {} -> err TooFewTyParams {} -> err RecursiveTypeDecls {} -> err+ SchemaMismatch i t1 t2 ->+ SchemaMismatch i !$ (apSubst su t1) !$ (apSubst su t2) TypeMismatch src pa t1 t2 -> TypeMismatch src pa !$ (apSubst su t1) !$ (apSubst su t2) RecursiveType src pa t1 t2 -> RecursiveType src pa !$ (apSubst su t1) !$ (apSubst su t2) UnsolvedGoals gs -> UnsolvedGoals !$ apSubst su gs@@ -248,7 +303,20 @@ TypeShadowing {} -> err MissingModTParam {} -> err MissingModVParam {} -> err+ MissingModParam {} -> err + FunctorInstanceMissingArgument {} -> err+ FunctorInstanceBadArgument {} -> err+ FunctorInstanceMissingName {} -> err+ FunctorInstanceBadBacktick {} -> err++ UnsupportedFFIKind {} -> err+ UnsupportedFFIType src e -> UnsupportedFFIType src !$ apSubst su e++ NestedConstraintGuard {} -> err+ DeclarationRequiresSignatureCtrGrd {} -> err+ InvalidConstraintGuard p -> InvalidConstraintGuard $! apSubst su p+ TemporaryError {} -> err @@ -261,6 +329,7 @@ TooManyTySynParams {} -> Set.empty TooFewTyParams {} -> Set.empty RecursiveTypeDecls {} -> Set.empty+ SchemaMismatch _ t1 t2 -> fvs (t1,t2) TypeMismatch _ _ t1 t2 -> fvs (t1,t2) RecursiveType _ _ t1 t2 -> fvs (t1,t2) UnsolvedGoals gs -> fvs gs@@ -283,7 +352,20 @@ TypeShadowing {} -> Set.empty MissingModTParam {} -> Set.empty MissingModVParam {} -> Set.empty+ MissingModParam {} -> Set.empty + FunctorInstanceMissingArgument {} -> Set.empty+ FunctorInstanceBadArgument {} -> Set.empty+ FunctorInstanceMissingName {} -> Set.empty+ FunctorInstanceBadBacktick {} -> Set.empty++ UnsupportedFFIKind {} -> Set.empty+ UnsupportedFFIType _ t -> fvs t++ NestedConstraintGuard {} -> Set.empty+ DeclarationRequiresSignatureCtrGrd {} -> Set.empty+ InvalidConstraintGuard p -> fvs p+ TemporaryError {} -> Set.empty instance PP Warning where@@ -307,6 +389,10 @@ text "Defaulting" <+> pp (tvarDesc d) <+> text "to" <+> ppWithNames names ty + NonExhaustivePropGuards n ->+ text "Could not prove that the constraint guards used in defining" <+> + pp n <+> text "were exhaustive."+ instance PP (WithNames Error) where ppPrec _ (WithNames err names) = case err of@@ -321,8 +407,13 @@ UnexpectedTypeWildCard -> addTVarsDescsAfter names err $- nested "Wild card types are not allowed in this context"- "(e.g., they cannot be used in type synonyms)."+ nested "Wild card types are not allowed in this context" $+ vcat [ "They cannot be used in:"+ , bullets [ "type synonyms"+ , "FFI declarations"+ , "declarations with constraint guards"+ ]+ ] KindMismatch mbsrc k1 k2 -> addTVarsDescsAfter names err $@@ -370,6 +461,14 @@ ++ ppCtxt pa ++ ["When checking" <+> pp src] + SchemaMismatch i t1 t2 ->+ addTVarsDescsAfter names err $+ nested ("Type mismatch in module parameter" <+> quotes (pp i)) $+ vcat $+ [ "Expected type:" <+> ppWithNames names t1+ , "Actual type:" <+> ppWithNames names t2+ ]+ UnsolvableGoals gs -> explainUnsolvable names gs UnsolvedGoals gs@@ -456,6 +555,91 @@ "Missing definition for type parameter" <+> quotes (pp (thing x)) MissingModVParam x -> "Missing definition for value parameter" <+> quotes (pp (thing x))++ MissingModParam x ->+ "Missing module parameter" <+> quotes (pp x)++ FunctorInstanceMissingArgument i ->+ "Missing functor argument" <+> quotes (pp i)++ FunctorInstanceBadArgument i ->+ "Functor does not have parameter" <+> quotes (pp i)++ FunctorInstanceMissingName ns i ->+ "Functor argument does not define" <+> sayNS <+> "parameter" <+>+ quotes (pp i)+ where+ sayNS =+ case ns of+ NSValue -> "value"+ NSType -> "type"+ NSModule -> "module"++ FunctorInstanceBadBacktick bad ->+ case bad of+ BIPolymorphicArgument i x ->+ nested "Value parameter may not have a polymorphic type:" $+ bullets+ [ "Module parameter:" <+> pp i+ , "Value parameter:" <+> pp x+ , "When instantiatiating a functor using parameterization,"+ $$ "the value parameters need to have a simple type."+ ]++ BINested what ->+ nested "Invalid declarations in parameterized instantiation:" $+ bullets $+ [ it <+> pp n+ | (w,n) <- what+ , let it = case w of+ BIFunctor -> "functor"+ BIInterface -> "interface"+ BIPrimitive -> "primitive"+ BIAbstractType -> "abstract type"+ BIForeign -> "foreign import"+ ] +++ [ "A functor instantiated using parameterization," $$+ "may not contain nested functors, interfaces, or primitives."+ ]+ BIMultipleParams x ->+ nested "Repeated parameter name in parameterized instantiation:" $+ bullets+ [ "Parameter name:" <+> pp x+ , "Parameterized instantiation requires distinct parameter names"+ ]+ ++ UnsupportedFFIKind src param k ->+ nested "Kind of type variable unsupported for FFI: " $+ vcat+ [ pp param <+> colon <+> pp k+ , "Only type variables of kind" <+> pp KNum <+> "are supported"+ , "When checking" <+> pp src ]++ UnsupportedFFIType src t -> vcat+ [ ppWithNames names t+ , "When checking" <+> pp src ]++ NestedConstraintGuard d ->+ vcat [ "Local declaration" <+> backticks (pp d)+ <+> "may not use constraint guards."+ , "Constraint guards may only appear at the top-level of a module."+ ]++ DeclarationRequiresSignatureCtrGrd d ->+ vcat [ "The declaration of" <+> backticks (pp d) <+>+ "requires a full type signature,"+ , "because it is part of a recursive group with constraint guards."+ ]++ InvalidConstraintGuard p ->+ let d = case tNoUser p of+ TCon tc _ -> pp tc+ _ -> ppWithNames names p+ in+ vcat [ backticks d <+> "may not be used in a constraint guard."+ , "Constraint guards support only numeric comparisons and `fin`."+ ] TemporaryError doc -> doc where
+ src/Cryptol/TypeCheck/FFI.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE Safe #-}++-- | Checking and conversion of 'Type's to 'FFIType's.+module Cryptol.TypeCheck.FFI+ ( toFFIFunType+ ) where++import Data.Bifunctor+import Data.Containers.ListUtils+import Data.Either++import Cryptol.TypeCheck.FFI.Error+import Cryptol.TypeCheck.FFI.FFIType+import Cryptol.TypeCheck.SimpType+import Cryptol.TypeCheck.Type+import Cryptol.Utils.RecordMap+import Cryptol.Utils.Types++-- | Convert a 'Schema' to a 'FFIFunType', along with any 'Prop's that must be+-- satisfied for the 'FFIFunType' to be valid.+toFFIFunType :: Schema -> Either FFITypeError ([Prop], FFIFunType)+toFFIFunType (Forall params _ t) =+ -- Remove all type synonyms and simplify the type before processing it+ case go $ tRebuild' False t of+ Just (Right (props, fft)) -> Right+ -- Remove duplicate constraints+ (nubOrd $ map (fin . TVar . TVBound) params ++ props, fft)+ Just (Left errs) -> Left $ FFITypeError t $ FFIBadComponentTypes errs+ Nothing -> Left $ FFITypeError t FFINotFunction+ where go (TCon (TC TCFun) [argType, retType]) = Just+ case toFFIType argType of+ Right (ps, ffiArgType) ->+ case go retType of+ Just (Right (ps', ffiFunType)) -> Right+ ( ps ++ ps'+ , ffiFunType+ { ffiArgTypes = ffiArgType : ffiArgTypes ffiFunType } )+ Just (Left errs) -> Left errs+ Nothing ->+ case toFFIType retType of+ Right (ps', ffiRetType) -> Right+ ( ps ++ ps'+ , FFIFunType+ { ffiTParams = params+ , ffiArgTypes = [ffiArgType], .. } )+ Left err -> Left [err]+ Left err -> Left+ case go retType of+ Just (Right _) -> [err]+ Just (Left errs) -> err : errs+ Nothing ->+ case toFFIType retType of+ Right _ -> [err]+ Left err' -> [err, err']+ go _ = Nothing++-- | Convert a 'Type' to a 'FFIType', along with any 'Prop's that must be+-- satisfied for the 'FFIType' to be valid.+toFFIType :: Type -> Either FFITypeError ([Prop], FFIType)+toFFIType t =+ case t of+ TCon (TC TCBit) [] -> Right ([], FFIBool)+ (toFFIBasicType -> Just r) -> (\fbt -> ([], FFIBasic fbt)) <$> r+ TCon (TC TCSeq) _ ->+ (\(szs, fbt) -> (map fin szs, FFIArray szs fbt)) <$> go t+ where go (toFFIBasicType -> Just r) =+ case r of+ Right fbt -> Right ([], fbt)+ Left err -> Left $ FFITypeError t $ FFIBadComponentTypes [err]+ go (TCon (TC TCSeq) [sz, ty]) = first (sz:) <$> go ty+ go _ = Left $ FFITypeError t FFIBadArrayType+ TCon (TC (TCTuple _)) ts ->+ case partitionEithers $ map toFFIType ts of+ ([], unzip -> (pss, fts)) -> Right (concat pss, FFITuple fts)+ (errs, _) -> Left $ FFITypeError t $ FFIBadComponentTypes errs+ TRec tMap ->+ case sequence resMap of+ Right resMap' -> Right $ FFIRecord <$>+ recordMapAccum (\ps (ps', ft) -> (ps' ++ ps, ft)) [] resMap'+ Left _ -> Left $ FFITypeError t $+ FFIBadComponentTypes $ lefts $ displayElements resMap+ where resMap = fmap toFFIType tMap+ _ -> Left $ FFITypeError t FFIBadType++-- | Convert a 'Type' to a 'FFIBasicType', returning 'Nothing' if it isn't a+-- basic type and 'Left' if it is but there was some other issue with it.+toFFIBasicType :: Type -> Maybe (Either FFITypeError FFIBasicType)+toFFIBasicType t =+ case t of+ TCon (TC TCSeq) [TCon (TC (TCNum n)) [], TCon (TC TCBit) []]+ | n <= 8 -> word FFIWord8+ | n <= 16 -> word FFIWord16+ | n <= 32 -> word FFIWord32+ | n <= 64 -> word FFIWord64+ | otherwise -> Just $ Left $ FFITypeError t FFIBadWordSize+ where word = Just . Right . FFIBasicVal . FFIWord n+ TCon (TC TCFloat) [TCon (TC (TCNum e)) [], TCon (TC (TCNum p)) []]+ | (e, p) == float32ExpPrec -> float FFIFloat32+ | (e, p) == float64ExpPrec -> float FFIFloat64+ | otherwise -> Just $ Left $ FFITypeError t FFIBadFloatSize+ where float = Just . Right . FFIBasicVal . FFIFloat e p+ TCon (TC TCInteger) [] -> integer Nothing+ TCon (TC TCIntMod) [n] -> integer $ Just n+ TCon (TC TCRational) [] -> Just $ Right $ FFIBasicRef FFIRational+ _ -> Nothing+ where integer = Just . Right . FFIBasicRef . FFIInteger++fin :: Type -> Prop+fin t = TCon (PC PFin) [t]
+ src/Cryptol/TypeCheck/FFI/Error.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Safe #-}++-- | Errors from typechecking foreign functions.+module Cryptol.TypeCheck.FFI.Error where++import Control.DeepSeq+import GHC.Generics++import Cryptol.TypeCheck.PP+import Cryptol.TypeCheck.Subst+import Cryptol.TypeCheck.Type++data FFITypeError = FFITypeError Type FFITypeErrorReason+ deriving (Show, Generic, NFData)++data FFITypeErrorReason+ = FFIBadWordSize+ | FFIBadFloatSize+ | FFIBadArrayType+ | FFIBadComponentTypes [FFITypeError]+ | FFIBadType+ | FFINotFunction+ deriving (Show, Generic, NFData)++instance TVars FFITypeError where+ apSubst su (FFITypeError t r) = FFITypeError !$ apSubst su t !$ apSubst su r++instance TVars FFITypeErrorReason where+ apSubst su r =+ case r of+ FFIBadWordSize -> r+ FFIBadFloatSize -> r+ FFIBadArrayType -> r+ FFIBadComponentTypes errs -> FFIBadComponentTypes !$ apSubst su errs+ FFIBadType -> r+ FFINotFunction -> r++instance FVS FFITypeError where+ fvs (FFITypeError t r) = fvs (t, r)++instance FVS FFITypeErrorReason where+ fvs r =+ case r of+ FFIBadWordSize -> mempty+ FFIBadFloatSize -> mempty+ FFIBadArrayType -> mempty+ FFIBadComponentTypes errs -> fvs errs+ FFIBadType -> mempty+ FFINotFunction -> mempty++instance PP (WithNames FFITypeError) where+ ppPrec _ (WithNames (FFITypeError t r) names) =+ nest 2 $ "Type unsupported for FFI:" $$+ vcat+ [ ppWithNames names t+ , "Due to:"+ , ppWithNames names r ]++instance PP (WithNames FFITypeErrorReason) where+ ppPrec _ (WithNames r names) =+ case r of+ FFIBadWordSize -> vcat+ [ "Unsupported word size"+ , "Only words of up to 64 bits are supported" ]+ FFIBadFloatSize -> vcat+ [ "Unsupported Float format"+ , "Only Float32 and Float64 are supported" ]+ FFIBadArrayType -> vcat+ [ "Unsupported sequence element type"+ , "Only words or floats are supported as the element type of"+ , "(possibly multidimensional) sequences"+ ]+ FFIBadComponentTypes errs ->+ indent 2 $ vcat $ map (ppWithNames names) errs+ FFIBadType -> vcat+ [ "Only Bit, words, floats, Integer, Z, Rational, sequences, or structs"+ , "or tuples of the above are supported as FFI argument or return types"+ ]+ FFINotFunction -> "FFI binding must be a function"
+ src/Cryptol/TypeCheck/FFI/FFIType.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE Safe #-}++-- | This module defines a nicer intermediate representation of Cryptol types+-- allowed for the FFI, which the typechecker generates then stores in the AST.+-- This way the FFI evaluation code does not have to examine the raw type+-- signatures again.+module Cryptol.TypeCheck.FFI.FFIType where++import Control.DeepSeq+import GHC.Generics++import Cryptol.TypeCheck.Type+import Cryptol.Utils.Ident+import Cryptol.Utils.RecordMap++-- | Type of a foreign function.+data FFIFunType = FFIFunType+ { -- | Note: any type variables within this function type must be bound here.+ ffiTParams :: [TParam]+ , ffiArgTypes :: [FFIType]+ , ffiRetType :: FFIType }+ deriving (Show, Generic, NFData)++-- | Type of a value that can be passed to or returned from a foreign function.+data FFIType+ = FFIBool+ | FFIBasic FFIBasicType+ -- | [n][m][p]T --> FFIArray [n, m, p] T+ | FFIArray [Type] FFIBasicType+ | FFITuple [FFIType]+ | FFIRecord (RecordMap Ident FFIType)+ deriving (Show, Generic, NFData)++-- | Types which can be elements of FFI arrays.+data FFIBasicType+ = FFIBasicVal FFIBasicValType+ | FFIBasicRef FFIBasicRefType+ deriving (Show, Generic, NFData)++-- | Basic type which is passed and returned directly by value.+data FFIBasicValType+ = FFIWord+ Integer -- ^ The size of the Cryptol type+ FFIWordSize -- ^ The machine word size that it corresponds to+ | FFIFloat+ Integer -- ^ Exponent+ Integer -- ^ Precision+ FFIFloatSize -- ^ The machine float size that it corresponds to+ deriving (Show, Generic, NFData)++data FFIWordSize+ = FFIWord8+ | FFIWord16+ | FFIWord32+ | FFIWord64+ deriving (Show, Generic, NFData)++data FFIFloatSize+ = FFIFloat32+ | FFIFloat64+ deriving (Show, Generic, NFData)++-- | Basic type which is passed and returned by reference through a parameter.+data FFIBasicRefType+ = FFIInteger+ (Maybe Type) -- ^ Modulus (Just for Z, Nothing for Integer)+ | FFIRational+ deriving (Show, Generic, NFData)
src/Cryptol/TypeCheck/Infer.hs view
@@ -14,13 +14,16 @@ {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE BlockArguments #-}-{-# LANGUAGE Safe #-} -- See Note [-Wincomplete-uni-patterns and irrefutable patterns] in Cryptol.TypeCheck.TypePat {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}+{-# LANGUAGE LambdaCase #-}+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}+{-# HLINT ignore "Redundant <$>" #-}+{-# HLINT ignore "Redundant <&>" #-} module Cryptol.TypeCheck.Infer ( checkE , checkSigB- , inferModule+ , inferTopModule , inferBinds , checkTopDecls )@@ -30,7 +33,7 @@ import qualified Data.Text as Text -import Cryptol.ModuleSystem.Name (lookupPrimDecl,nameLoc)+import Cryptol.ModuleSystem.Name (lookupPrimDecl,nameLoc, nameIdent) import Cryptol.Parser.Position import qualified Cryptol.Parser.AST as P import qualified Cryptol.ModuleSystem.Exports as P@@ -43,36 +46,58 @@ checkPropSyn,checkNewtype, checkParameterType, checkPrimType,- checkParameterConstraints)+ checkParameterConstraints,+ checkPropGuards) import Cryptol.TypeCheck.Instantiate import Cryptol.TypeCheck.Subst (listSubst,apSubst,(@@),isEmptySubst) import Cryptol.TypeCheck.Unify(rootPath)+import Cryptol.TypeCheck.Module+import Cryptol.TypeCheck.FFI+import Cryptol.TypeCheck.FFI.FFIType import Cryptol.Utils.Ident import Cryptol.Utils.Panic(panic) import Cryptol.Utils.RecordMap+import Cryptol.IR.TraverseNames(mapNames)+import Cryptol.Utils.PP (pp) import qualified Data.Map as Map import Data.Map (Map) import qualified Data.Set as Set-import Data.List(foldl',sortBy,groupBy)+import Data.List(foldl', sortBy, groupBy, partition) import Data.Either(partitionEithers) import Data.Maybe(isJust, fromMaybe, mapMaybe)-import Data.List(partition) import Data.Ratio(numerator,denominator) import Data.Traversable(forM) import Data.Function(on)-import Control.Monad(zipWithM,unless,foldM,forM_,mplus)+import Control.Monad(zipWithM, unless, foldM, forM_, mplus, zipWithM,+ unless, foldM, forM_, mplus, when) +-- import Debug.Trace+-- import Cryptol.TypeCheck.PP +inferTopModule :: P.Module Name -> InferM TCTopEntity+inferTopModule m =+ case P.mDef m of+ P.NormalModule ds ->+ do newModuleScope (thing (P.mName m)) (P.exportedDecls ds)+ checkTopDecls ds+ proveModuleTopLevel+ endModule -inferModule :: P.Module Name -> InferM Module-inferModule m =- do newModuleScope (thing (P.mName m)) (map thing (P.mImports m))- (P.modExports m)- checkTopDecls (P.mDecls m)- proveModuleTopLevel- endModule+ P.FunctorInstance f as inst ->+ do mb <- doFunctorInst (P.ImpTop <$> P.mName m) f as inst Nothing+ case mb of+ Just mo -> pure mo+ Nothing -> panic "inferModule" ["Didnt' get a module"] + P.InterfaceModule sig ->+ do newTopSignatureScope (thing (P.mName m))+ checkSignature sig+ endTopSignature++++ -- | Construct a Prelude primitive in the parsed AST. mkPrim :: String -> InferM (P.Expr Name) mkPrim str =@@ -157,8 +182,6 @@ cs <- getCallStacks if cs then pure (ELocated r e') else pure e' - P.ENeg {} -> mono- P.EComplement {} -> mono P.EGenerate {} -> mono P.ETuple {} -> mono@@ -178,6 +201,7 @@ P.ETypeVal {} -> mono P.EFun {} -> mono P.ESplit {} -> mono+ P.EPrefix {} -> mono P.EParens e -> appTys e ts tGoal P.EInfix a op _ b -> appTys (P.EVar (thing op) `P.EApp` a `P.EApp` b) ts tGoal@@ -221,14 +245,6 @@ checkHasType t tGoal return e' - P.ENeg e ->- do prim <- mkPrim "negate"- checkE (P.EApp prim e) tGoal-- P.EComplement e ->- do prim <- mkPrim "complement"- checkE (P.EApp prim e) tGoal- P.EGenerate e -> do prim <- mkPrim "generate" checkE (P.EApp prim e) tGoal@@ -454,6 +470,12 @@ P.EInfix a op _ b -> checkE (P.EVar (thing op) `P.EApp` a `P.EApp` b) tGoal + P.EPrefix op e ->+ do prim <- mkPrim case op of+ P.PrefixNeg -> "negate"+ P.PrefixComplement -> "complement"+ checkE (P.EApp prim e) tGoal+ P.EParens e -> checkE e tGoal @@ -464,7 +486,7 @@ -- { _ | fs } ~~> \r -> { r | fs } Nothing ->- do r <- newParamName NSValue (packIdent "r")+ do r <- newLocalName NSValue (packIdent "r") let p = P.PVar Located { srcRange = nameLoc r, thing = r } fe = P.EFun P.emptyFunDesc [p] (P.EUpd (Just (P.EVar r)) fs) checkE fe tGoal@@ -490,7 +512,7 @@ v1 <- checkE v (WithSource (tFun ft ft) src eloc) -- XXX: ^ may be used a different src? d <- newHasGoal s (twsType tGoal) ft- tmp <- newParamName NSValue (packIdent "rf")+ tmp <- newLocalName NSValue (packIdent "rf") let e' = EVar tmp pure ( hasDoSet d e' (EApp v1 (hasDoSelect d e')) `EWhere`@@ -734,15 +756,18 @@ newGoals CtComprehension [ pFin n' ] return (m1 : ms', Map.insertWith (\_ old -> old) x t ds, tMul n n') --- | @inferBinds isTopLevel isRec binds@ performs inference for a--- strongly-connected component of 'P.Bind's.--- If any of the members of the recursive group are already marked--- as monomorphic, then we don't do generalization.--- If @isTopLevel@ is true,--- any bindings without type signatures will be generalized. If it is--- false, and the mono-binds flag is enabled, no bindings without type--- signatures will be generalized, but bindings with signatures will--- be unaffected.+{- | @inferBinds isTopLevel isRec binds@ performs inference for a+strongly-connected component of 'P.Bind's.+If any of the members of the recursive group are already marked+as monomorphic, then we don't do generalization.+If @isTopLevel@ is true,+any bindings without type signatures will be generalized. If it is+false, and the mono-binds flag is enabled, no bindings without type+signatures will be generalized, but bindings with signatures will+be unaffected.++-}+ inferBinds :: Bool -> Bool -> [P.Bind Name] -> InferM [Decl] inferBinds isTopLevel isRec binds = do -- when mono-binds is enabled, and we're not checking top-level@@ -790,6 +815,8 @@ genCs <- generalize bs1 cs return (done,genCs) + checkNumericConstraintGuardsOK isTopLevel sigs noSigs+ rec let exprMap = Map.fromList (map monoUse genBs) (doneBs, genBs) <- check exprMap@@ -817,9 +844,40 @@ withQs = foldl' appP withTys qs +{-+Here we also check that:+ * Numeric constraint guards appear only at the top level+ * All definitions in a recursive groups with numberic constraint guards+ have signatures +The reason is to avoid interference between local constraints coming+from the guards and type inference. It might be possible to+relex these requirements, but this requires some more careful thought on+the interaction between the two, and the effects on pricniple types.+-}+checkNumericConstraintGuardsOK ::+ Bool -> [P.Bind Name] -> [P.Bind Name] -> InferM ()+checkNumericConstraintGuardsOK isTopLevel haveSig noSig =+ do unless isTopLevel+ (mapM_ (mkErr NestedConstraintGuard) withGuards)+ unless (null withGuards)+ (mapM_ (mkErr DeclarationRequiresSignatureCtrGrd) noSig)+ where+ mkErr f b =+ do let nm = P.bName b+ inRange (srcRange nm) (recordError (f (nameIdent (thing nm)))) + withGuards = filter hasConstraintGuards haveSig+ -- When desugaring constraint guards we check that they have signatures,+ -- so no need to look at noSig + hasConstraintGuards b =+ case thing (P.bDef b) of+ P.DPropGuards {} -> True+ _ -> False+++ {- | Come up with a type for recursive calls to a function, and decide how we are going to be checking the binding. Returns: (Name, type or schema, computation to check binding)@@ -836,7 +894,12 @@ case bSignature of Just s ->- do s1 <- checkSchema AllowWildCards s+ do let wildOk = case thing bDef of+ P.DForeign {} -> NoWildCards+ P.DPrim -> NoWildCards+ P.DExpr {} -> AllowWildCards+ P.DPropGuards {} -> NoWildCards+ s1 <- checkSchema wildOk s return ((name, ExtVar (fst s1)), Left (checkSigB b s1)) Nothing@@ -930,8 +993,9 @@ genE e = foldr ETAbs (foldr EProofAbs (apSubst su e) qs) asPs genB d = d { dDefinition = case dDefinition d of- DExpr e -> DExpr (genE e)- DPrim -> DPrim+ DExpr e -> DExpr (genE e)+ DPrim -> DPrim+ DForeign t -> DForeign t , dSignature = Forall asPs qs $ apSubst su $ sType $ dSignature d }@@ -953,6 +1017,8 @@ P.DPrim -> panic "checkMonoB" ["Primitive with no signature?"] + P.DForeign -> panic "checkMonoB" ["Foreign with no signature?"]+ P.DExpr e -> do let nm = thing (P.bName b) let tGoal = WithSource t (DefinitionOf nm) (getLoc b)@@ -967,70 +1033,253 @@ , dDoc = P.bDoc b } + P.DPropGuards _ ->+ tcPanic "checkMonoB"+ [ "Used constraint guards without a signature at "+ , show . pp $ P.bName b ]+ -- XXX: Do we really need to do the defaulting business in two different places? checkSigB :: P.Bind Name -> (Schema,[Goal]) -> InferM Decl-checkSigB b (Forall as asmps0 t0, validSchema) = case thing (P.bDef b) of+checkSigB b (Forall as asmps0 t0, validSchema) =+ let name = thing (P.bName b) in+ case thing (P.bDef b) of - -- XXX what should we do with validSchema in this case?- P.DPrim ->- do return Decl { dName = thing (P.bName b)- , dSignature = Forall as asmps0 t0- , dDefinition = DPrim- , dPragmas = P.bPragmas b- , dInfix = P.bInfix b- , dFixity = P.bFixity b- , dDoc = P.bDoc b- }+ -- XXX what should we do with validSchema in this case?+ P.DPrim ->+ return Decl+ { dName = name+ , dSignature = Forall as asmps0 t0+ , dDefinition = DPrim+ , dPragmas = P.bPragmas b+ , dInfix = P.bInfix b+ , dFixity = P.bFixity b+ , dDoc = P.bDoc b+ } - P.DExpr e0 ->- inRangeMb (getLoc b) $- withTParams as $- do (e1,cs0) <- collectGoals $- do let nm = thing (P.bName b)- tGoal = WithSource t0 (DefinitionOf nm) (getLoc b)- e1 <- checkFun (P.FunDesc (Just nm) 0) (P.bParams b) e0 tGoal- addGoals validSchema- () <- simplifyAllConstraints -- XXX: using `asmps` also?- return e1+ P.DForeign -> do+ let loc = getLoc b+ name' = thing $ P.bName b+ src = DefinitionOf name'+ inRangeMb loc do+ -- Ensure all type params are of kind #+ forM_ as \a ->+ when (tpKind a /= KNum) $+ recordErrorLoc loc $ UnsupportedFFIKind src a $ tpKind a+ withTParams as do+ ffiFunType <-+ case toFFIFunType (Forall as asmps0 t0) of+ Right (props, ffiFunType) -> ffiFunType <$ do+ ffiGoals <- traverse (newGoal (CtFFI name')) props+ proveImplication True (Just name') as asmps0 $+ validSchema ++ ffiGoals+ Left err -> do+ recordErrorLoc loc $ UnsupportedFFIType src err+ -- Just a placeholder type+ pure FFIFunType+ { ffiTParams = as, ffiArgTypes = []+ , ffiRetType = FFITuple [] }+ pure Decl { dName = thing (P.bName b)+ , dSignature = Forall as asmps0 t0+ , dDefinition = DForeign ffiFunType+ , dPragmas = P.bPragmas b+ , dInfix = P.bInfix b+ , dFixity = P.bFixity b+ , dDoc = P.bDoc b+ } - asmps1 <- applySubstPreds asmps0- cs <- applySubstGoals cs0+ P.DExpr e0 ->+ inRangeMb (getLoc b) $+ withTParams as $ do+ (t, asmps, e2) <- checkBindDefExpr [] asmps0 e0 - let findKeep vs keep todo =- let stays (_,cvs) = not $ Set.null $ Set.intersection vs cvs- (yes,perhaps) = partition stays todo- (stayPs,newVars) = unzip yes- in case stayPs of- [] -> (keep,map fst todo)- _ -> findKeep (Set.unions (vs:newVars)) (stayPs ++ keep) perhaps+ return Decl+ { dName = name+ , dSignature = Forall as asmps t+ , dDefinition = DExpr (foldr ETAbs (foldr EProofAbs e2 asmps) as)+ , dPragmas = P.bPragmas b+ , dInfix = P.bInfix b+ , dFixity = P.bFixity b+ , dDoc = P.bDoc b+ } - let -- if a goal mentions any of these variables, we'll commit to- -- solving it now.- stickyVars = Set.fromList (map tpVar as) `Set.union` fvs asmps1- (stay,leave) = findKeep stickyVars []- [ (c, fvs c) | c <- cs ]+ P.DPropGuards cases0 ->+ inRangeMb (getLoc b) $+ withTParams as $ do+ asmps1 <- applySubstPreds asmps0+ t1 <- applySubst t0+ cases1 <- mapM checkPropGuardCase cases0 - addGoals leave+ exh <- checkExhaustive (P.bName b) as asmps1 (map fst cases1)+ unless exh $+ -- didn't prove exhaustive i.e. none of the guarding props+ -- necessarily hold+ recordWarning (NonExhaustivePropGuards name) + let schema = Forall as asmps1 t1 - su <- proveImplication (Just (thing (P.bName b))) as asmps1 stay- extendSubst su+ return Decl+ { dName = name+ , dSignature = schema+ , dDefinition = DExpr+ (foldr ETAbs+ (foldr EProofAbs+ (EPropGuards cases1 t1)+ asmps1)+ as)+ , dPragmas = P.bPragmas b+ , dInfix = P.bInfix b+ , dFixity = P.bFixity b+ , dDoc = P.bDoc b+ } - let asmps = concatMap pSplitAnd (apSubst su asmps1)- t <- applySubst t0- e2 <- applySubst e1 - return Decl- { dName = thing (P.bName b)- , dSignature = Forall as asmps t- , dDefinition = DExpr (foldr ETAbs (foldr EProofAbs e2 asmps) as)- , dPragmas = P.bPragmas b- , dInfix = P.bInfix b- , dFixity = P.bFixity b- , dDoc = P.bDoc b- }+ where + checkBindDefExpr ::+ [Prop] -> [Prop] -> P.Expr Name -> InferM (Type, [Prop], Expr)+ checkBindDefExpr asmpsSign asmps1 e0 = do + (e1,cs0) <- collectGoals $ do+ let nm = thing (P.bName b)+ tGoal = WithSource t0 (DefinitionOf nm) (getLoc b)+ e1 <- checkFun (P.FunDesc (Just nm) 0) (P.bParams b) e0 tGoal+ addGoals validSchema+ () <- simplifyAllConstraints -- XXX: using `asmps` also?+ return e1+ asmps2 <- applySubstPreds asmps1+ cs <- applySubstGoals cs0++ let findKeep vs keep todo =+ let stays (_,cvs) = not $ Set.null $ Set.intersection vs cvs+ (yes,perhaps) = partition stays todo+ (stayPs,newVars) = unzip yes+ in case stayPs of+ [] -> (keep,map fst todo)+ _ -> findKeep (Set.unions (vs:newVars)) (stayPs ++ keep) perhaps++ let -- if a goal mentions any of these variables, we'll commit to+ -- solving it now.+ stickyVars = Set.fromList (map tpVar as) `Set.union` fvs asmps2+ (stay,leave) = findKeep stickyVars []+ [ (c, fvs c) | c <- cs ]++ addGoals leave++ -- includes asmpsSign for the sake of implication, but doesn't actually+ -- include them in the resulting asmps+ su <- proveImplication True (Just (thing (P.bName b))) as (asmpsSign <> asmps2) stay+ extendSubst su++ let asmps = concatMap pSplitAnd (apSubst su asmps2)+ t <- applySubst t0+ e2 <- applySubst e1++ pure (t, asmps, e2)++++{- |+Given a DPropGuards of the form++@+f : {...} A+f | (B1, B2) => ... + | (C1, C2, C2) => ... +@++we check that it is exhaustive by trying to prove the following+implications:++@+ A /\ ~B1 => C1 /\ C2 /\ C3+ A /\ ~B2 => C1 /\ C2 /\ C3+@++The implications were derive by the following general algorithm:+- Find that @(C1, C2, C3)@ is the guard that has the most conjuncts, so we+ will keep it on the RHS of the generated implications in order to minimize+ the number of implications we need to check.+- Negate @(B1, B2)@ which yields @(~B1) \/ (~B2)@. This is a disjunction, so+ we need to consider a branch for each disjunct --- one branch gets the+ assumption @~B1@ and another branch gets the assumption @~B2@. Each+ branch's implications need to be proven independently.++-}+checkExhaustive :: Located Name -> [TParam] -> [Prop] -> [[Prop]] -> InferM Bool+checkExhaustive name as asmps guards =+ case sortBy cmpByLonger guards of+ [] -> pure False -- XXX: we should check the asmps are unsatisfiable+ longest : rest -> doGoals (theAlts rest) (map toGoal longest)++ where+ cmpByLonger props1 props2 = compare (length props2) (length props1)+ -- reversed, so that longets is first++ theAlts :: [[Prop]] -> [[Prop]]+ theAlts = map concat . sequence . map chooseNeg++ -- Choose one of the things to negate+ chooseNeg ps =+ case ps of+ [] -> []+ p : qs -> (pNegNumeric p ++ qs) : [ p : alts | alts <- chooseNeg qs ]++++ -- Try to validate all cases+ doGoals todo gs =+ case todo of+ [] -> pure True+ alt : more ->+ do ok <- canProve (asmps ++ alt) gs+ if ok then doGoals more gs+ else pure False++ toGoal :: Prop -> Goal+ toGoal prop =+ Goal+ { goalSource = CtPropGuardsExhaustive (thing name)+ , goalRange = srcRange name+ , goal = prop+ }++ canProve :: [Prop] -> [Goal] -> InferM Bool+ canProve asmps' goals =+ tryProveImplication (Just (thing name)) as asmps' goals++{- | This function does not validate anything---it just translates into+the type-checkd syntax. The actual validation of the guard will happen+when the (automatically generated) function corresponding to the guard is+checked, assuming 'ExpandpropGuards' did its job correctly.++-}+checkPropGuardCase :: P.PropGuardCase Name -> InferM ([Prop],Expr)+checkPropGuardCase (P.PropGuardCase guards e0) =+ do ps <- checkPropGuards guards+ tys <- mapM (`checkType` Nothing) ts+ let rhsTs = foldl ETApp (getV eV) tys+ rhsPs = foldl (\e _p -> EProofApp e) rhsTs ps+ rhs = foldl EApp rhsPs (map getV es)+ pure (ps,rhs)++ where+ (e1,es) = P.asEApps e0+ (eV,ts) = case e1 of+ P.EAppT ex1 tis -> (ex1, map getT tis)+ _ -> (e1, [])++ getV ex =+ case ex of+ P.EVar x -> EVar x+ _ -> bad "Expression is not a variable."++ getT ti =+ case ti of+ P.PosInst t -> t+ P.NamedInst {} -> bad "Unexpeceted NamedInst"++ bad msg = panic "checkPropGuardCase" [msg]+ -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- @@ -1059,29 +1308,115 @@ do t <- checkPrimType (P.tlValue tl) (thing <$> P.tlDoc tl) addPrimType t - P.DParameterType ty ->- do t <- checkParameterType ty (P.ptDoc ty)- addParamType t - P.DParameterConstraint cs ->- do cs1 <- checkParameterConstraints cs+ P.DInterfaceConstraint _ cs ->+ inRange (srcRange cs)+ do cs1 <- checkParameterConstraints [ cs { thing = c } | c <- thing cs ] addParameterConstraints cs1 - P.DParameterFun pf ->- do x <- checkParameterFun pf- addParamFun x- P.DModule tl ->- do let P.NestedModule m = P.tlValue tl- newSubmoduleScope (thing (P.mName m)) (map thing (P.mImports m))- (P.modExports m)- checkTopDecls (P.mDecls m)- endSubmodule+ selectorScope+ case P.mDef m of - P.DImport {} -> pure ()- P.Include {} -> panic "checkTopDecl" [ "Unexpected `inlude`" ]+ P.NormalModule ds ->+ do newSubmoduleScope (thing (P.mName m))+ (thing <$> P.tlDoc tl)+ (P.exportedDecls ds)+ checkTopDecls ds+ proveModuleTopLevel+ endSubmodule + P.FunctorInstance f as inst ->+ do let doc = thing <$> P.tlDoc tl+ _ <- doFunctorInst (P.ImpNested <$> P.mName m) f as inst doc+ pure () + P.InterfaceModule sig ->+ do let doc = P.thing <$> P.tlDoc tl+ inRange (srcRange (P.mName m))+ do newSignatureScope (thing (P.mName m)) doc+ checkSignature sig+ endSignature+++ where P.NestedModule m = P.tlValue tl++ P.DModParam p ->+ inRange (srcRange (P.mpSignature p))+ do let binds = P.mpRenaming p+ suMap = Map.fromList [ (y,x) | (x,y) <- Map.toList binds ]+ actualName x = Map.findWithDefault x x suMap++ ips <- lookupSignature (thing (P.mpSignature p))+ let actualTys = [ mapNames actualName mp+ | mp <- Map.elems (mpnTypes ips) ]+ actualTS = [ mapNames actualName ts+ | ts <- Map.elems (mpnTySyn ips)+ ]+ actualCtrs = [ mapNames actualName prop+ | prop <- mpnConstraints ips ]+ actualVals = [ mapNames actualName vp+ | vp <- Map.elems (mpnFuns ips) ]++ param =+ ModParam+ { mpName = P.mpName p+ , mpIface = thing (P.mpSignature p)+ , mpQual = P.mpAs p+ , mpParameters =+ ModParamNames+ { mpnTypes = Map.fromList [ (mtpName tp, tp)+ | tp <- actualTys ]+ , mpnTySyn = Map.fromList [ (tsName ts, ts)+ | ts <- actualTS ]+ , mpnConstraints = actualCtrs+ , mpnFuns = Map.fromList [ (mvpName vp, vp)+ | vp <- actualVals ]+ , mpnDoc = thing <$> P.mpDoc p+ }+ }++ mapM_ addParamType actualTys+ addParameterConstraints actualCtrs+ mapM_ addParamFun actualVals+ mapM_ addTySyn actualTS+ addModParam param++ P.DImport {} -> pure ()+ P.Include {} -> bad "Include"+ P.DParamDecl {} -> bad "DParamDecl"+++ bad x = panic "checkTopDecl" [ x ]+++checkSignature :: P.Signature Name -> InferM ()+checkSignature sig =+ do forM_ (P.sigTypeParams sig) \pt ->+ addParamType =<< checkParameterType pt++ mapM_ checkSigDecl (P.sigDecls sig)++ addParameterConstraints =<<+ checkParameterConstraints (P.sigConstraints sig)++ forM_ (P.sigFunParams sig) \f ->+ addParamFun =<< checkParameterFun f++ proveModuleTopLevel++checkSigDecl :: P.SigDecl Name -> InferM ()+checkSigDecl decl =+ case decl of++ P.SigTySyn ts mbD ->+ addTySyn =<< checkTySyn ts mbD++ P.SigPropSyn ps mbD ->+ addTySyn =<< checkPropSyn ps mbD+++ checkDecl :: Bool -> P.Decl Name -> Maybe Text -> InferM () checkDecl isTopLevel d mbDoc = case d of@@ -1116,8 +1451,8 @@ checkParameterFun :: P.ParameterFun Name -> InferM ModVParam checkParameterFun x = do (s,gs) <- checkSchema NoWildCards (P.pfSchema x)- su <- proveImplication (Just (thing (P.pfName x)))- (sVars s) (sProps s) gs+ su <- proveImplication False (Just (thing (P.pfName x)))+ (sVars s) (sProps s) gs unless (isEmptySubst su) $ panic "checkParameterFun" ["Subst not empty??"] let n = thing (P.pfName x)
src/Cryptol/TypeCheck/InferTypes.hs view
@@ -27,7 +27,7 @@ import Cryptol.TypeCheck.Subst import Cryptol.TypeCheck.TypePat import Cryptol.TypeCheck.SimpType(tMax)-import Cryptol.Utils.Ident (ModName, PrimIdent(..), preludeName)+import Cryptol.Utils.Ident (PrimIdent(..), preludeName) import Cryptol.Utils.Panic(panic) import Cryptol.Utils.Misc(anyJust) @@ -182,7 +182,8 @@ compare x y = compare (goal x) (goal y) data HasGoal = HasGoal- { hasName :: !Int+ { hasName :: !Int -- ^ This is the "name" of the constraint,+ -- used to find the solution for ellaboration. , hasGoal :: Goal } deriving Show @@ -219,7 +220,10 @@ | CtPartialTypeFun Name -- ^ Use of a partial type function. | CtImprovement | CtPattern TypeSource -- ^ Constraints arising from type-checking patterns- | CtModuleInstance ModName -- ^ Instantiating a parametrized module+ | CtModuleInstance Range -- ^ Instantiating a parametrized module+ | CtPropGuardsExhaustive Name -- ^ Checking that a use of prop guards is exhastive+ | CtFFI Name -- ^ Constraints on a foreign declaration required+ -- by the FFI (e.g. sequences must be finite) deriving (Show, Generic, NFData) selSrc :: Selector -> TypeSource@@ -247,6 +251,8 @@ CtImprovement -> src CtPattern _ -> src CtModuleInstance _ -> src+ CtPropGuardsExhaustive _ -> src+ CtFFI _ -> src instance FVS Goal where@@ -352,7 +358,9 @@ CtPartialTypeFun f -> "use of partial type function" <+> pp f CtImprovement -> "examination of collected goals" CtPattern ad -> "checking a pattern:" <+> pp ad- CtModuleInstance n -> "module instantiation" <+> pp n+ CtModuleInstance r -> "module instantiation at" <+> pp r+ CtPropGuardsExhaustive n -> "exhaustion check for prop guards used in defining" <+> pp n+ CtFFI f -> "declaration of foreign function" <+> pp f ppUse :: Expr -> Doc ppUse expr =
src/Cryptol/TypeCheck/Interface.hs view
@@ -1,73 +1,83 @@+{-# LANGUAGE Safe #-}+ module Cryptol.TypeCheck.Interface where import qualified Data.Map as Map+import Data.Set(Set)+import qualified Data.Set as Set -import Cryptol.Utils.Ident(Namespace(..)) import Cryptol.ModuleSystem.Interface+import Cryptol.ModuleSystem.Exports(allExported) import Cryptol.TypeCheck.AST +-- | Information about a declaration to be stored an in interface. mkIfaceDecl :: Decl -> IfaceDecl mkIfaceDecl d = IfaceDecl { ifDeclName = dName d , ifDeclSig = dSignature d+ , ifDeclIsPrim = case dDefinition d of+ DPrim {} -> True+ _ -> False , ifDeclPragmas = dPragmas d , ifDeclInfix = dInfix d , ifDeclFixity = dFixity d , ifDeclDoc = dDoc d } --- | Generate an Iface from a typechecked module.-genIface :: ModuleG mname -> IfaceG mname-genIface m = Iface- { ifModName = mName m-- , ifPublic = IfaceDecls- { ifTySyns = tsPub- , ifNewtypes = ntPub- , ifAbstractTypes = atPub- , ifDecls = dPub- , ifModules = mPub- }-- , ifPrivate = IfaceDecls- { ifTySyns = tsPriv- , ifNewtypes = ntPriv- , ifAbstractTypes = atPriv- , ifDecls = dPriv- , ifModules = mPriv- }-- , ifParams = IfaceParams- { ifParamTypes = mParamTypes m- , ifParamConstraints = mParamConstraints m- , ifParamFuns = mParamFuns m- }+-- | Compute information about the names in a module.+genIfaceNames :: ModuleG name -> IfaceNames name+genIfaceNames m = IfaceNames+ { ifsName = mName m+ , ifsNested = mNested m+ , ifsDefines = genModDefines m+ , ifsPublic = allExported (mExports m)+ , ifsDoc = mDoc m }- where - (tsPub,tsPriv) =- Map.partitionWithKey (\ qn _ -> qn `isExportedType` mExports m )- (mTySyns m)- (ntPub,ntPriv) =- Map.partitionWithKey (\ qn _ -> qn `isExportedType` mExports m )- (mNewtypes m)-- (atPub,atPriv) =- Map.partitionWithKey (\qn _ -> qn `isExportedType` mExports m)- (mPrimTypes m)+-- | Things defines by a module+genModDefines :: ModuleG name -> Set Name+genModDefines m =+ Set.unions+ [ Map.keysSet (mTySyns m)+ , Map.keysSet (mNewtypes m)+ , Set.fromList (map ntConName (Map.elems (mNewtypes m)))+ , Map.keysSet (mPrimTypes m)+ , Set.fromList (map dName (concatMap groupDecls (mDecls m)))+ , Map.keysSet (mSubmodules m)+ , Map.keysSet (mFunctors m)+ , Map.keysSet (mSignatures m)+ ] `Set.difference` nestedInSet (mNested m)+ where+ nestedInSet = Set.unions . map inNested . Set.toList+ inNested x = case Map.lookup x (mSubmodules m) of+ Just y -> ifsDefines y `Set.union` nestedInSet (ifsNested y)+ Nothing -> Set.empty -- must be signature or a functor - (dPub,dPriv) =- Map.partitionWithKey (\ qn _ -> qn `isExportedBind` mExports m)- $ Map.fromList [ (qn,mkIfaceDecl d) | dg <- mDecls m- , d <- groupDecls dg- , let qn = dName d- ]+genIface :: ModuleG name -> IfaceG name+genIface m = genIfaceWithNames (genIfaceNames m) m - (mPub,mPriv) =- Map.partitionWithKey (\ qn _ -> isExported NSModule qn (mExports m))- $ mSubModules m+-- | Generate an Iface from a typechecked module.+genIfaceWithNames :: IfaceNames name -> ModuleG ignored -> IfaceG name+genIfaceWithNames names m =+ Iface+ { ifNames = names + , ifDefines = IfaceDecls+ { ifTySyns = mTySyns m+ , ifNewtypes = mNewtypes m+ , ifAbstractTypes = mPrimTypes m+ , ifDecls = Map.fromList [ (qn,mkIfaceDecl d)+ | dg <- mDecls m+ , d <- groupDecls dg+ , let qn = dName d+ ]+ , ifModules = mSubmodules m+ , ifSignatures = mSignatures m+ , ifFunctors = genIface <$> mFunctors m+ } + , ifParams = mParams m+ }
src/Cryptol/TypeCheck/Kind.hs view
@@ -7,7 +7,7 @@ -- Portability : portable {-# LANGUAGE RecursiveDo #-}-{-# LANGUAGE Safe #-}+{-# LANGUAGE BlockArguments #-} -- See Note [-Wincomplete-uni-patterns and irrefutable patterns] in Cryptol.TypeCheck.TypePat {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Cryptol.TypeCheck.Kind@@ -19,6 +19,7 @@ , checkPropSyn , checkParameterType , checkParameterConstraints+ , checkPropGuards ) where import qualified Cryptol.Parser.AST as P@@ -38,9 +39,7 @@ import Data.Maybe(fromMaybe) import Data.Function(on) import Data.Text (Text)-import Control.Monad(unless,when)--+import Control.Monad(unless,when,mplus) -- | Check a type signature. Returns validated schema, and any implicit -- constraints that we inferred.@@ -66,14 +65,38 @@ Nothing -> id Just r -> inRange r +{- | Validate parsed propositions that appear in the guard of a PropGuard.++ * Note that we don't validate the well-formedness constraints here---instead,+ they'd be validated when the signature for the auto generated+ function corresponding guard is checked.++ * We also check that there are no wild-cards in the constraints.+-}+checkPropGuards :: [Located (P.Prop Name)] -> InferM [Prop]+checkPropGuards props =+ do (newPs,_gs) <- collectGoals (mapM check props)+ pure newPs+ where+ check lp =+ inRange (srcRange lp)+ do let p = thing lp+ (_,ps) <- withTParams NoWildCards schemaParam [] (checkProp p)+ case tNoUser ps of+ TCon (PC x) _ | x `elem` [PEqual,PNeq,PGeq,PFin,PTrue] -> pure ()+ _ -> recordError (InvalidConstraintGuard ps)+ pure ps+++ -- | Check a module parameter declarations. Nothing much to check, -- we just translate from one syntax to another.-checkParameterType :: P.ParameterType Name -> Maybe Text -> InferM ModTParam-checkParameterType a mbDoc =- do let k = cvtK (P.ptKind a)+checkParameterType :: P.ParameterType Name -> InferM ModTParam+checkParameterType a =+ do let mbDoc = P.ptDoc a+ k = cvtK (P.ptKind a) n = thing (P.ptName a)- return ModTParam { mtpKind = k, mtpName = n, mtpDoc = mbDoc- , mtpNumber = P.ptNumber a }+ return ModTParam { mtpKind = k, mtpName = n, mtpDoc = mbDoc } -- | Check a type-synonym declaration.@@ -111,7 +134,7 @@ -- | Check a newtype declaration. -- XXX: Do something with constraints. checkNewtype :: P.Newtype Name -> Maybe Text -> InferM Newtype-checkNewtype (P.Newtype x as fs) mbD =+checkNewtype (P.Newtype x as con fs) mbD = do ((as1,fs1),gs) <- collectGoals $ inRange (srcRange x) $ do r <- withTParams NoWildCards newtypeParam as $@@ -123,6 +146,7 @@ return Newtype { ntName = thing x , ntParams = as1 , ntConstraints = map goal gs+ , ntConName = con , ntFields = fs1 , ntDoc = mbD }@@ -386,8 +410,16 @@ P.TUser x ts -> checkTUser x ts k - P.TParens t -> doCheckType t k+ P.TParens t mb ->+ do newK <- case (k, cvtK <$> mb) of+ (Just a, Just b) ->+ do unless (a == b)+ (kRecordError (KindMismatch Nothing a b))+ pure (Just b)+ (a,b) -> pure (mplus a b) + doCheckType t newK+ P.TInfix t x _ u-> doCheckType (P.TUser (thing x) [t, u]) k P.TTyApp _fs -> do kRecordError BareTypeApp@@ -398,7 +430,7 @@ -- | Validate a parsed proposition. checkProp :: P.Prop Name -- ^ Proposition that need to be checked- -> KindM Type -- ^ Checked representation+ -> KindM Prop -- ^ Checked representation checkProp (P.CType t) = doCheckType t (Just KProp) @@ -411,5 +443,3 @@ | k1 /= k2 = do kRecordError (KindMismatch Nothing k1 k2) kNewType TypeErrorPlaceHolder k1 checkKind t _ _ = return t--
+ src/Cryptol/TypeCheck/Module.hs view
@@ -0,0 +1,376 @@+{-# Language BlockArguments, ImplicitParams #-}+module Cryptol.TypeCheck.Module (doFunctorInst) where++import Data.List(partition)+import Data.Text(Text)+import Data.Map(Map)+import qualified Data.Map as Map+import Data.Set (Set)+import qualified Data.Set as Set+import Control.Monad(unless,forM_)+++import Cryptol.Utils.Panic(panic)+import Cryptol.Utils.Ident(Ident,Namespace(..),isInfixIdent)+import Cryptol.Parser.Position (Range,Located(..), thing)+import qualified Cryptol.Parser.AST as P+import Cryptol.ModuleSystem.Name(nameIdent)+import Cryptol.ModuleSystem.Interface+ ( IfaceG(..), IfaceDecls(..), IfaceNames(..), IfaceDecl(..)+ , filterIfaceDecls+ )+import Cryptol.TypeCheck.AST+import Cryptol.TypeCheck.Error+import Cryptol.TypeCheck.Subst(Subst,listParamSubst,apSubst,mergeDistinctSubst)+import Cryptol.TypeCheck.Solve(proveImplication)+import Cryptol.TypeCheck.Monad+import Cryptol.TypeCheck.Instantiate(instantiateWith)+import Cryptol.TypeCheck.ModuleInstance+import Cryptol.TypeCheck.ModuleBacktickInstance(MBQual, doBacktickInstance)++doFunctorInst ::+ Located (P.ImpName Name) {- ^ Name for the new module -} ->+ Located (P.ImpName Name) {- ^ Functor being instantiated -} ->+ P.ModuleInstanceArgs Name {- ^ Instance arguments -} ->+ Map Name Name+ {- ^ Instantitation. These is the renaming for the functor that arises from+ generativity (i.e., it is something that will make the names "fresh").+ -} ->+ Maybe Text {- ^ Documentation -} ->+ InferM (Maybe TCTopEntity)+doFunctorInst m f as inst doc =+ inRange (srcRange m)+ do mf <- lookupFunctor (thing f)+ argIs <- checkArity (srcRange f) mf as+ m2 <- do as2 <- mapM checkArg argIs+ let (tySus,decls) = unzip [ (su,ds) | DefinedInst su ds <- as2 ]+ let ?tSu = mergeDistinctSubst tySus+ ?vSu = inst+ let m1 = moduleInstance mf+ m2 = m1 { mName = m+ , mDoc = Nothing+ , mParamTypes = mempty+ , mParamFuns = mempty+ , mParamConstraints = mempty+ , mParams = mempty+ , mDecls = map NonRecursive (concat decls) +++ mDecls m1+ }+ let (tps,tcs,vps) =+ unzip3 [ (xs,cs,fs) | ParamInst xs cs fs <- as2 ]+ tpSet = Set.unions tps+ tpSet' = Set.map snd (Set.unions tps)+ emit p = Set.null (freeParams (thing p)+ `Set.intersection` tpSet')++ (emitPs,delayPs) = partition emit (mParamConstraints m1)++ forM_ emitPs \lp ->+ newGoals (CtModuleInstance (srcRange lp)) [thing lp]++ doBacktickInstance tpSet+ (map thing delayPs ++ concat tcs)+ (Map.unions vps)+ m2++ case thing m of+ P.ImpTop mn -> newModuleScope mn (mExports m2)+ P.ImpNested mn -> newSubmoduleScope mn doc (mExports m2)++ mapM_ addTySyn (Map.elems (mTySyns m2))+ mapM_ addNewtype (Map.elems (mNewtypes m2))+ mapM_ addPrimType (Map.elems (mPrimTypes m2))+ addSignatures (mSignatures m2)+ addSubmodules (mSubmodules m2)+ addFunctors (mFunctors m2)+ mapM_ addDecls (mDecls m2)++ case thing m of+ P.ImpTop {} -> Just <$> endModule+ P.ImpNested {} -> endSubmodule >> pure Nothing+++data ActualArg =+ UseParameter ModParam -- ^ Instantiate using this parameter+ | UseModule (IfaceG ()) -- ^ Instantiate using this module+ | AddDeclParams -- ^ Instantiate by adding parameters+++++{- | Validate a functor application, just checking the argument names.+The result associates a module parameter with the concrete way it should+be instantiated, which could be:++ * `Left` instanciate using another parameter that is in scope+ * `Right` instanciate using a module, with the given interface+-}+checkArity ::+ Range {- ^ Location for reporting errors -} ->+ ModuleG () {- ^ The functor being instantiated -} ->+ P.ModuleInstanceArgs Name {- ^ The arguments -} ->+ InferM [(Range, ModParam, ActualArg)]+ {- ^ Associates functor parameters with the interfaces of the+ instantiating modules -}+checkArity r mf args =+ case args of++ P.DefaultInstArg arg ->+ let i = Located { srcRange = srcRange arg+ , thing = head (Map.keys ps0)+ }+ in checkArgs [] ps0 [ P.ModuleInstanceNamedArg i arg ]++ P.NamedInstArgs as -> checkArgs [] ps0 as++ P.DefaultInstAnonArg {} -> panic "checkArity" [ "DefaultInstAnonArg" ]+ where+ ps0 = mParams mf++ checkArgs done ps as =+ case as of++ [] -> do forM_ (Map.keys ps) \p ->+ recordErrorLoc (Just r) (FunctorInstanceMissingArgument p)+ pure done++ P.ModuleInstanceNamedArg ll lm : more ->+ case Map.lookup (thing ll) ps of+ Just i ->+ do arg <- case thing lm of+ P.ModuleArg m -> Just . UseModule <$> lookupModule m+ P.ParameterArg p ->+ do mb <- lookupModParam p+ case mb of+ Nothing ->+ do inRange (srcRange lm)+ (recordError (MissingModParam p))+ pure Nothing+ Just a -> pure (Just (UseParameter a))+ P.AddParams -> pure (Just AddDeclParams)+ let next = case arg of+ Nothing -> done+ Just a -> (srcRange lm, i, a) : done+ checkArgs next (Map.delete (thing ll) ps) more++ Nothing ->+ do recordErrorLoc (Just (srcRange ll))+ (FunctorInstanceBadArgument (thing ll))+ checkArgs done ps more+++data ArgInst = DefinedInst Subst [Decl] -- ^ Argument that defines the params+ | ParamInst (Set (MBQual TParam)) [Prop] (Map (MBQual Name) Type)+ -- ^ Argument that add parameters+ -- The type parameters are in their module type parameter+ -- form (i.e., tpFlav is TPModParam)++++{- | Check the argument to a functor parameter.+Returns:++ * A substitution which will replace the parameter types with+ the concrete types that were provided++ * Some declarations that define the parameters in terms of the provided+ values.++ * XXX: Extra parameters for instantiation by adding params+-}+checkArg ::+ (Range, ModParam, ActualArg) -> InferM ArgInst+checkArg (r,expect,actual') =+ case actual' of+ AddDeclParams -> paramInst+ UseParameter {} -> definedInst+ UseModule {} -> definedInst++ where+ paramInst =+ do let as = Set.fromList+ (map (qual . mtpParam) (Map.elems (mpnTypes params)))+ cs = map thing (mpnConstraints params)+ check = checkSimpleParameterValue r (mpName expect)+ qual a = (mpQual expect, a)+ fs <- Map.mapMaybeWithKey (\_ v -> v) <$> mapM check (mpnFuns params)+ pure (ParamInst as cs (Map.mapKeys qual fs))++ definedInst =+ do tRens <- mapM (checkParamType r tyMap) (Map.toList (mpnTypes params))+ let renSu = listParamSubst (concat tRens)++ {- Note: the constraints from the signature are already added to the+ constraints for the functor and they are checked all at once in+ doFunctorInst -}+++ vDecls <- concat <$>+ mapM (checkParamValue r vMap)+ [ s { mvpType = apSubst renSu (mvpType s) }+ | s <- Map.elems (mpnFuns params) ]++ pure (DefinedInst renSu vDecls)+++ params = mpParameters expect++ -- Things provided by the argument module+ tyMap :: Map Ident (Kind, Type)+ vMap :: Map Ident (Name, Schema)+ (tyMap,vMap) =+ case actual' of+ UseParameter mp ->+ ( nameMapToIdentMap fromTP (mpnTypes ps)+ , nameMapToIdentMap fromVP (mpnFuns ps)+ )+ where+ ps = mpParameters mp+ fromTP tp = (mtpKind tp, TVar (TVBound (mtpParam tp)))+ fromVP vp = (mvpName vp, mvpType vp)++ UseModule actual ->+ ( Map.unions [ nameMapToIdentMap fromTS (ifTySyns decls)+ , nameMapToIdentMap fromNewtype (ifNewtypes decls)+ , nameMapToIdentMap fromPrimT (ifAbstractTypes decls)+ ]++ , nameMapToIdentMap fromD (ifDecls decls)+ )++ where+ localNames = ifsPublic (ifNames actual)+ isLocal x = x `Set.member` localNames++ -- Things defined by the argument module+ decls = filterIfaceDecls isLocal (ifDefines actual)++ fromD d = (ifDeclName d, ifDeclSig d)+ fromTS ts = (kindOf ts, tsDef ts)+ fromNewtype nt = (kindOf nt, TNewtype nt [])+ fromPrimT pt = (kindOf pt, TCon (abstractTypeTC pt) [])++ AddDeclParams -> panic "checkArg" ["AddDeclParams"]++++nameMapToIdentMap :: (a -> b) -> Map Name a -> Map Ident b+nameMapToIdentMap f m =+ Map.fromList [ (nameIdent n, f v) | (n,v) <- Map.toList m ]+++++-- | Check a type parameter to a module.+checkParamType ::+ Range {- ^ Location for error reporting -} ->+ Map Ident (Kind,Type) {- ^ Actual types -} ->+ (Name,ModTParam) {- ^ Type parameter -} ->+ InferM [(TParam,Type)] {- ^ Mapping from parameter name to actual type -}+checkParamType r tyMap (name,mp) =+ let i = nameIdent name+ expectK = mtpKind mp+ in+ case Map.lookup i tyMap of+ Nothing ->+ do recordErrorLoc (Just r) (FunctorInstanceMissingName NSType i)+ pure []+ Just (actualK,actualT) ->+ do unless (expectK == actualK)+ (recordErrorLoc (Just r)+ (KindMismatch (Just (TVFromModParam name))+ expectK actualK))+ pure [(mtpParam mp, actualT)]++-- | Check a value parameter to a module.+checkParamValue ::+ Range {- ^ Location for error reporting -} ->+ Map Ident (Name,Schema) {- ^ Actual values -} ->+ ModVParam {- ^ The parameter we are checking -} ->+ InferM [Decl] {- ^ Mapping from parameter name to definition -}+checkParamValue r vMap mp =+ let name = mvpName mp+ i = nameIdent name+ expectT = mvpType mp+ in case Map.lookup i vMap of+ Nothing ->+ do recordErrorLoc (Just r) (FunctorInstanceMissingName NSValue i)+ pure []+ Just actual ->+ do e <- mkParamDef r (name,expectT) actual+ let d = Decl { dName = name+ , dSignature = expectT+ , dDefinition = DExpr e+ , dPragmas = []+ , dInfix = isInfixIdent (nameIdent name)+ , dFixity = mvpFixity mp+ , dDoc = mvpDoc mp+ }++ pure [d]++++checkSimpleParameterValue ::+ Range {- ^ Location for error reporting -} ->+ Ident {- ^ Name of functor parameter -} ->+ ModVParam {- ^ Module parameter -} ->+ InferM (Maybe Type) {- ^ Type to add to things, `Nothing` on err -}+checkSimpleParameterValue r i mp =+ case (sVars sch, sProps sch) of+ ([],[]) -> pure (Just (sType sch))+ _ ->+ do recordErrorLoc (Just r)+ (FunctorInstanceBadBacktick+ (BIPolymorphicArgument i (nameIdent (mvpName mp))))+ pure Nothing+ where+ sch = mvpType mp+++{- | Make an "adaptor" that instantiates the paramter into the form expected+by the functor. If the actual type is:++> {x} P => t++and the provided type is:++> f : {y} Q => s++The result, if successful would be:++ /\x \{P}. f @a {Q}++To do this we need to find types `a` to instantiate `y`, and prove that:+ {x} P => Q[a/y] /\ s = t+-}++mkParamDef ::+ Range {- ^ Location of instantiation for error reporting -} ->+ (Name,Schema) {- ^ Name and type of parameter -} ->+ (Name,Schema) {- ^ Name and type of actual argument -} ->+ InferM Expr+mkParamDef r (pname,wantedS) (arg,actualS) =+ do (e,todo) <- collectGoals+ $ withTParams (sVars wantedS)+ do (e,t) <- instantiateWith pname(EVar arg) actualS []+ props <- unify WithSource { twsType = sType wantedS+ , twsSource = TVFromModParam arg+ , twsRange = Just r+ }+ t+ newGoals (CtModuleInstance r) props+ pure e+ su <- proveImplication False+ (Just pname)+ (sVars wantedS)+ (sProps wantedS)+ todo+ let res = foldr ETAbs res1 (sVars wantedS)+ res1 = foldr EProofAbs (apSubst su e) (sProps wantedS)++ applySubst res++++
+ src/Cryptol/TypeCheck/ModuleBacktickInstance.hs view
@@ -0,0 +1,408 @@+{-# Language ImplicitParams #-}+{-# Language FlexibleInstances #-}+{-# Language RecursiveDo #-}+{-# Language BlockArguments #-}+{-# Language RankNTypes #-}+{-# Language OverloadedStrings #-}+module Cryptol.TypeCheck.ModuleBacktickInstance+ ( MBQual+ , doBacktickInstance+ ) where++import Data.Set(Set)+import qualified Data.Set as Set+import Data.Map(Map)+import qualified Data.Map as Map+import MonadLib+import Data.List(group,sort)+import Data.Maybe(mapMaybe)+import qualified Data.Text as Text++import Cryptol.Utils.Ident(ModPath(..), modPathIsOrContains,Namespace(..)+ , Ident, mkIdent, identText+ , ModName, modNameChunksText )+import Cryptol.Utils.PP(pp)+import Cryptol.Utils.Panic(panic)+import Cryptol.Utils.RecordMap(RecordMap,recordFromFields,recordFromFieldsErr)+import Cryptol.Parser.Position+import Cryptol.ModuleSystem.Name(+ nameModPath, nameModPathMaybe, nameIdent, mapNameIdent)+import Cryptol.TypeCheck.AST+import Cryptol.TypeCheck.Error+import qualified Cryptol.TypeCheck.Monad as TC+++type MBQual a = (Maybe ModName, a)++{- | Rewrite declarations to add the given module parameters.+Assumes the renaming due to the instantiation has already happened.+The module being rewritten should not contain any nested functors+(or module with only top-level constraints) because it is not clear+how to parameterize the parameters.+-}+doBacktickInstance ::+ Set (MBQual TParam) ->+ [Prop] ->+ Map (MBQual Name) Type ->+ ModuleG (Located (ImpName Name)) ->+ TC.InferM (ModuleG (Located (ImpName Name)))+doBacktickInstance as ps mp m+ | null as && null ps && Map.null mp = pure m+ | otherwise =+ runReaderT+ RO { isOurs = \x -> case nameModPathMaybe x of+ Nothing -> False+ Just y -> ourPath `modPathIsOrContains` y+ , tparams = Set.toList as+ , constraints = ps+ , vparams = mp+ , newNewtypes = Map.empty+ }++ do unless (null bad)+ (recordError (FunctorInstanceBadBacktick (BINested bad)))++ rec+ ts <- doAddParams nt mTySyns+ nt <- doAddParams nt mNewtypes+ ds <- doAddParams nt mDecls++ pure m+ { mTySyns = ts+ , mNewtypes = nt+ , mDecls = ds+ }++ where+ bad = mkBad mFunctors BIFunctor+ ++ mkBad mPrimTypes BIAbstractType+ ++ mkBad mSignatures BIInterface++ mkBad sel a = [ (a,k) | k <- Map.keys (sel m) ]++ ourPath = case thing (mName m) of+ ImpTop mo -> TopModule mo+ ImpNested mo -> Nested (nameModPath mo) (nameIdent mo)++ doAddParams nt sel =+ mapReader (\ro -> ro { newNewtypes = nt }) (addParams (sel m))+++type RewM = ReaderT RO TC.InferM++recordError :: Error -> RewM ()+recordError e = lift (TC.recordError e)++data RO = RO+ { isOurs :: Name -> Bool+ , tparams :: [MBQual TParam]+ , constraints :: [Prop]+ , vparams :: Map (MBQual Name) Type+ , newNewtypes :: Map Name Newtype+ }+++class AddParams t where+ addParams :: t -> RewM t++instance AddParams a => AddParams (Map Name a) where+ addParams = mapM addParams++instance AddParams a => AddParams [a] where+ addParams = mapM addParams++instance AddParams Newtype where+ addParams nt =+ do (tps,cs) <- newTypeParams TPNewtypeParam+ rProps <- rewTypeM tps (ntConstraints nt)+ rFields <- rewTypeM tps (ntFields nt)+ pure nt+ { ntParams = pDecl tps ++ ntParams nt+ , ntConstraints = cs ++ rProps+ , ntFields = rFields+ }++instance AddParams TySyn where+ addParams ts =+ do (tps,cs) <- newTypeParams TPTySynParam+ rProps <- rewTypeM tps (tsConstraints ts)+ rDef <- rewTypeM tps (tsDef ts)+ pure ts+ { tsParams = pDecl tps ++ tsParams ts+ , tsConstraints = cs ++ rProps+ , tsDef = rDef+ }++instance AddParams DeclGroup where+ addParams dg =+ case dg of+ Recursive ds -> Recursive <$> addParams ds+ NonRecursive d -> NonRecursive <$> addParams d++instance AddParams Decl where+ addParams d =+ case dDefinition d of+ DPrim -> bad BIPrimitive+ DForeign {} -> bad BIForeign+ DExpr e ->+ do (tps,cs) <- newTypeParams TPSchemaParam+ (vps,bs) <- newValParams tps+ let s = dSignature d++ ty1 <- rewTypeM tps (sType s)+ ps1 <- rewTypeM tps (sProps s)+ let ty2 = foldr tFun ty1 (map snd bs)++ e1 <- rewValM tps (length cs) vps e+ let (das,e2) = splitWhile splitTAbs e1+ (dcs,e3) = splitWhile splitProofAbs e2+ e4 = foldr (uncurry EAbs) e3 bs+ e5 = foldr EProofAbs e4 (cs ++ dcs)+ e6 = foldr ETAbs e5 (pDecl tps ++ das)++ s1 = Forall+ { sVars = pDecl tps ++ sVars s+ , sProps = cs ++ ps1+ , sType = ty2+ }++ pure d { dDefinition = DExpr e6+ , dSignature = s1+ }+ where+ bad w =+ do recordError (FunctorInstanceBadBacktick (BINested [(w,dName d)]))+ pure d++data Params decl use = Params+ { pDecl :: [decl]+ , pUse :: [use]+ , pSubst :: Map decl use+ }++noParams :: Params decl use+noParams = Params+ { pDecl = []+ , pUse = []+ , pSubst = Map.empty+ }++qualLabel :: Maybe ModName -> Ident -> Ident+qualLabel mb i =+ case mb of+ Nothing -> i+ Just mn ->+ let txt = Text.intercalate "'" (modNameChunksText mn ++ [identText i])+ in mkIdent txt+++type TypeParams = Params TParam Type+type ValParams = Params Name Expr++newTypeParams :: (Name -> TPFlavor) -> RewM (TypeParams,[Prop])+newTypeParams flav =+ do ro <- ask+ let newFlaf q = flav . mapNameIdent (qualLabel q)+ as <- lift (forM (tparams ro) \(q,a) -> TC.freshTParam (newFlaf q) a)+ let bad = [ x+ | x : _ : _ <- group (sort (map nameIdent (mapMaybe tpName as)))+ ]+ forM_ bad \i ->+ recordError (FunctorInstanceBadBacktick (BIMultipleParams i))++ let ts = map (TVar . TVBound) as+ su = Map.fromList (zip (map snd (tparams ro)) ts)+ ps = Params { pDecl = as, pUse = ts, pSubst = su }+ cs <- rewTypeM ps (constraints ro)+ pure (ps,cs)++-- Note: we pass all value parameters as a record+newValParams :: TypeParams -> RewM (ValParams, [(Name,Type)])+newValParams tps =+ do ro <- ask+ let vps = vparams ro+ if Map.null vps+ then pure (noParams, [])+ else do xts <- forM (Map.toList vps) \((q,x),t) ->+ do t1 <- rewTypeM tps t+ let l = qualLabel q (nameIdent x)+ pure (x, l, t1)+ let (xs,ls,ts) = unzip3 xts+ fs = zip ls ts+ sel l = RecordSel l (Just ls)++ t <- case recordFromFieldsErr fs of+ Right ok -> pure (TRec ok)+ Left (x,_) ->+ do recordError (FunctorInstanceBadBacktick+ (BIMultipleParams x))+ pure (TRec (recordFromFields fs))++ r <- lift (TC.newLocalName NSValue (mkIdent "params"))+ let e = EVar r+ pure+ ( Params+ { pDecl = [r]+ , pUse = [e]+ , pSubst = Map.fromList [ (x,ESel e (sel l))+ | (x,l) <- zip xs ls ]+ }+ , [ (r,t) ]+ )++liftRew ::+ ((?isOurs :: Name -> Bool, ?newNewtypes :: Map Name Newtype) => a) ->+ RewM a+liftRew x =+ do ro <- ask+ let ?isOurs = isOurs ro+ ?newNewtypes = newNewtypes ro+ pure x++rewTypeM :: RewType t => TypeParams -> t -> RewM t+rewTypeM ps x =+ do let ?tparams = ps+ liftRew rewType <*> pure x++rewValM :: RewVal t => TypeParams -> Int -> ValParams -> t -> RewM t+rewValM ts cs vs x =+ do let ?tparams = ts+ ?cparams = cs+ ?vparams = vs+ liftRew rew <*> pure x++class RewType t where+ rewType ::+ ( ?isOurs :: Name -> Bool+ , ?newNewtypes :: Map Name Newtype -- Lazy+ , ?tparams :: TypeParams+ ) => t -> t++instance RewType Type where+ rewType ty =+ case ty of++ TCon tc ts+ | TC (TCAbstract (UserTC x _)) <- tc+ , ?isOurs x -> TCon tc (pUse ?tparams ++ rewType ts)+ | otherwise -> TCon tc (rewType ts)++ TVar x ->+ case x of+ TVBound x' ->+ case Map.lookup x' (pSubst ?tparams) of+ Just t -> t+ Nothing -> ty+ TVFree {} -> panic "rawType" ["Free unification variable"]++ TUser f ts t+ | ?isOurs f -> TUser f (pUse ?tparams ++ rewType ts) (rewType t)+ | otherwise -> TUser f (rewType ts) (rewType t)++ TRec fs -> TRec (rewType fs)++ TNewtype tdef ts+ | ?isOurs nm -> TNewtype tdef' (pUse ?tparams ++ rewType ts)+ | otherwise -> TNewtype tdef (rewType ts)+ where+ nm = ntName tdef+ tdef' = case Map.lookup nm ?newNewtypes of+ Just yes -> yes+ Nothing -> panic "rewType" [ "Missing recursive newtype"+ , show (pp nm) ]++instance RewType a => RewType [a] where+ rewType = fmap rewType++instance RewType b => RewType (RecordMap a b) where+ rewType = fmap rewType++instance RewType Schema where+ rewType sch =+ Forall { sVars = sVars sch+ , sProps = rewType (sProps sch)+ , sType = rewType (sType sch)+ }+++class RewVal t where+ rew ::+ ( ?isOurs :: Name -> Bool+ , ?newNewtypes :: Map Name Newtype -- Lazy+ , ?tparams :: TypeParams+ , ?cparams :: Int -- Number of constraitns+ , ?vparams :: ValParams+ ) => t -> t++instance RewVal a => RewVal [a] where+ rew = fmap rew++instance RewVal b => RewVal (RecordMap a b) where+ rew = fmap rew++{- x as cs vs -->+ e (newAs ++ as) (newCS ++ cs) (newVS ++ vs)+-}+instance RewVal Expr where+ rew expr =+ case expr of+ EList es t -> EList (rew es) (rewType t)+ ETuple es -> ETuple (rew es)+ ERec fs -> ERec (rew fs)+ ESel e l -> ESel (rew e) l+ ESet t e1 s e2 -> ESet (rewType t) (rew e1) s (rew e2)+ EIf e1 e2 e3 -> EIf (rew e1) (rew e2) (rew e3)+ EComp t1 t2 e mss -> EComp (rewType t1) (rewType t2) (rew e) (rew mss)+ EVar x -> tryVarApp+ case Map.lookup x (pSubst ?vparams) of+ Just p -> p+ Nothing -> expr++ ETApp e t -> tryVarApp (ETApp (rew e) (rewType t))+ EProofApp e -> tryVarApp (EProofApp (rew e))++ EApp e1 e2 -> EApp (rew e1) (rew e2)+ ETAbs a e -> ETAbs a (rew e)+ EAbs x t e -> EAbs x (rewType t) (rew e)+ ELocated r e -> ELocated r (rew e)+ EProofAbs p e -> EProofAbs (rewType p) (rew e)+ EWhere e ds -> EWhere (rew e) (rew ds)+ EPropGuards gs t -> EPropGuards gs' (rewType t)+ where gs' = [ (rewType <$> p, rew e) | (p,e) <- gs ]++ where+ tryVarApp orElse =+ case splitExprInst expr of+ (EVar x, ts, cs) | ?isOurs x ->+ let ets = foldl ETApp (EVar x) (pUse ?tparams ++ rewType ts)+ eps = iterate EProofApp ets !! (?cparams + cs)+ evs = foldl EApp eps (pUse ?vparams)+ in evs+ _ -> orElse+++instance RewVal DeclGroup where+ rew dg =+ case dg of+ Recursive ds -> Recursive (rew ds)+ NonRecursive d -> NonRecursive (rew d)++instance RewVal Decl where+ rew d = d { dDefinition = rew (dDefinition d)+ , dSignature = rewType (dSignature d)+ }++instance RewVal DeclDef where+ rew def =+ case def of+ DPrim -> def+ DForeign {} -> def+ DExpr e -> DExpr (rew e)++instance RewVal Match where+ rew ma =+ case ma of+ From x t1 t2 e -> From x (rewType t1) (rewType t2) (rew e)+ Let d -> Let (rew d)++
+ src/Cryptol/TypeCheck/ModuleInstance.hs view
@@ -0,0 +1,168 @@+{-# Language ImplicitParams, ConstraintKinds #-}+module Cryptol.TypeCheck.ModuleInstance where++import Data.Map(Map)+import qualified Data.Map as Map+import Data.Set(Set)+import qualified Data.Set as Set++import Cryptol.Parser.Position(Located)+import Cryptol.ModuleSystem.Interface(IfaceNames(..))+import Cryptol.IR.TraverseNames(TraverseNames,mapNames)+import Cryptol.TypeCheck.AST+import Cryptol.TypeCheck.Subst(Subst,TVars,apSubst)+++{- | `?tSu` should be applied to all types.+ `?vSu` shoudl be applied to all values. -}+type Su = (?tSu :: Subst, ?vSu :: Map Name Name)++-- | Has value names but no types.+doVInst :: (Su, TraverseNames a) => a -> a+doVInst = mapNames (\x -> Map.findWithDefault x x ?vSu)++-- | Has types but not values.+doTInst :: (Su, TVars a) => a -> a+doTInst = apSubst ?tSu++-- | Has both value names and types.+doTVInst :: (Su, TVars a, TraverseNames a) => a -> a+doTVInst = apSubst ?tSu . doVInst++doMap :: (Su, ModuleInstance a) => Map Name a -> Map Name a+doMap mp =+ Map.fromList [ (moduleInstance x, moduleInstance d) | (x,d) <- Map.toList mp ]++doSet :: Su => Set Name -> Set Name+doSet = Set.fromList . map moduleInstance . Set.toList+++++class ModuleInstance t where+ moduleInstance :: Su => t -> t++instance ModuleInstance a => ModuleInstance [a] where+ moduleInstance = map moduleInstance++instance ModuleInstance a => ModuleInstance (Located a) where+ moduleInstance l = moduleInstance <$> l++instance ModuleInstance Name where+ moduleInstance = doVInst++instance ModuleInstance name => ModuleInstance (ImpName name) where+ moduleInstance x =+ case x of+ ImpTop t -> ImpTop t+ ImpNested n -> ImpNested (moduleInstance n)++instance ModuleInstance (ModuleG name) where+ moduleInstance m =+ Module { mName = mName m+ , mDoc = Nothing+ , mExports = doVInst (mExports m)+ , mParamTypes = doMap (mParamTypes m)+ , mParamFuns = doMap (mParamFuns m)+ , mParamConstraints = moduleInstance (mParamConstraints m)+ , mParams = moduleInstance <$> mParams m+ , mFunctors = doMap (mFunctors m)+ , mNested = doSet (mNested m)+ , mTySyns = doMap (mTySyns m)+ , mNewtypes = doMap (mNewtypes m)+ , mPrimTypes = doMap (mPrimTypes m)+ , mDecls = moduleInstance (mDecls m)+ , mSubmodules = doMap (mSubmodules m)+ , mSignatures = doMap (mSignatures m)+ }++instance ModuleInstance Type where+ moduleInstance = doTInst++instance ModuleInstance Schema where+ moduleInstance = doTInst++instance ModuleInstance TySyn where+ moduleInstance ts =+ TySyn { tsName = moduleInstance (tsName ts)+ , tsParams = tsParams ts+ , tsConstraints = moduleInstance (tsConstraints ts)+ , tsDef = moduleInstance (tsDef ts)+ , tsDoc = tsDoc ts+ }++instance ModuleInstance Newtype where+ moduleInstance nt =+ Newtype { ntName = moduleInstance (ntName nt)+ , ntParams = ntParams nt+ , ntConstraints = moduleInstance (ntConstraints nt)+ , ntConName = moduleInstance (ntConName nt)+ , ntFields = moduleInstance <$> ntFields nt+ , ntDoc = ntDoc nt+ }++instance ModuleInstance AbstractType where+ moduleInstance at =+ AbstractType { atName = moduleInstance (atName at)+ , atKind = atKind at+ , atCtrs = let (ps,cs) = atCtrs at+ in (ps, moduleInstance cs)+ , atFixitiy = atFixitiy at+ , atDoc = atDoc at+ }++instance ModuleInstance DeclGroup where+ moduleInstance dg =+ case dg of+ Recursive ds -> Recursive (moduleInstance ds)+ NonRecursive d -> NonRecursive (moduleInstance d)++instance ModuleInstance Decl where+ moduleInstance = doTVInst+++instance ModuleInstance name => ModuleInstance (IfaceNames name) where+ moduleInstance ns =+ IfaceNames { ifsName = moduleInstance (ifsName ns)+ , ifsNested = doSet (ifsNested ns)+ , ifsDefines = doSet (ifsDefines ns)+ , ifsPublic = doSet (ifsPublic ns)+ , ifsDoc = ifsDoc ns+ }++instance ModuleInstance ModParamNames where+ moduleInstance si =+ ModParamNames { mpnTypes = doMap (mpnTypes si)+ , mpnConstraints = moduleInstance (mpnConstraints si)+ , mpnFuns = doMap (mpnFuns si)+ , mpnTySyn = doMap (mpnTySyn si)+ , mpnDoc = mpnDoc si+ }++instance ModuleInstance ModTParam where+ moduleInstance mp =+ ModTParam { mtpName = moduleInstance (mtpName mp)+ , mtpKind = mtpKind mp+ , mtpDoc = mtpDoc mp+ }++instance ModuleInstance ModVParam where+ moduleInstance mp =+ ModVParam { mvpName = moduleInstance (mvpName mp)+ , mvpType = moduleInstance (mvpType mp)+ , mvpDoc = mvpDoc mp+ , mvpFixity = mvpFixity mp+ }++instance ModuleInstance ModParam where+ moduleInstance p =+ ModParam { mpName = mpName p+ , mpIface = moduleInstance (mpIface p)+ , mpParameters = moduleInstance (mpParameters p)+ , mpQual = mpQual p+ }+++++
src/Cryptol/TypeCheck/Monad.hs view
@@ -5,7 +5,6 @@ -- Maintainer : cryptol@galois.com -- Stability : provisional -- Portability : portable-{-# LANGUAGE Safe #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}@@ -22,6 +21,7 @@ import qualified Control.Applicative as A import qualified Control.Monad.Fail as Fail import Control.Monad.Fix(MonadFix(..))+import Data.Text(Text) import qualified Data.Map as Map import qualified Data.Set as Set import Data.Map (Map)@@ -38,13 +38,14 @@ import MonadLib hiding (mapM) import Cryptol.ModuleSystem.Name- (FreshM(..),Supply,mkParameter- , nameInfo, NameInfo(..),NameSource(..))+ (FreshM(..),Supply,mkLocal,asLocal+ , nameInfo, NameInfo(..),NameSource(..), nameTopModule)+import qualified Cryptol.ModuleSystem.Interface as If import Cryptol.Parser.Position import qualified Cryptol.Parser.AST as P import Cryptol.TypeCheck.AST import Cryptol.TypeCheck.Subst-import Cryptol.TypeCheck.Interface(genIface)+import Cryptol.TypeCheck.Interface(genIfaceWithNames,genIfaceNames) import Cryptol.TypeCheck.Unify(doMGU, runResult, UnificationError(..) , Path, rootPath) import Cryptol.TypeCheck.InferTypes@@ -54,8 +55,8 @@ import qualified Cryptol.TypeCheck.SimpleSolver as Simple import qualified Cryptol.TypeCheck.Solver.SMT as SMT import Cryptol.TypeCheck.PP(NameMap)-import Cryptol.Utils.PP(pp, (<+>), text,commaSep,brackets)-import Cryptol.Utils.Ident(Ident,Namespace(..))+import Cryptol.Utils.PP(pp, (<+>), text,commaSep,brackets,debugShowUniques)+import Cryptol.Utils.Ident(Ident,Namespace(..),ModName) import Cryptol.Utils.Panic(panic) -- | Information needed for type inference.@@ -64,15 +65,16 @@ , inpVars :: Map Name Schema -- ^ Variables that are in scope , inpTSyns :: Map Name TySyn -- ^ Type synonyms that are in scope , inpNewtypes :: Map Name Newtype -- ^ Newtypes in scope- , inpAbstractTypes :: Map Name AbstractType -- ^ Abstract types in scope+ , inpAbstractTypes :: Map Name AbstractType -- ^ Abstract types in scope+ , inpSignatures :: !(Map Name ModParamNames) -- ^ Signatures in scope + , inpTopModules :: ModName -> Maybe (ModuleG (), If.IfaceG ())+ , inpTopSignatures :: ModName -> Maybe ModParamNames+ -- When typechecking a module these start off empty. -- We need them when type-checking an expression at the command -- line, for example.- , inpParamTypes :: !(Map Name ModTParam) -- ^ Type parameters- , inpParamConstraints :: !([Located Prop]) -- ^ Constraints on parameters- , inpParamFuns :: !(Map Name ModVParam) -- ^ Value parameters-+ , inpParams :: !ModParamNames , inpNameSeeds :: NameSeeds -- ^ Private state of type-checker , inpMonoBinds :: Bool -- ^ Should local bindings without@@ -120,24 +122,35 @@ io $ modifyIORef' iSolveCounter (+1) runInferM :: TVars a => InferInput -> InferM a -> IO (InferOutput a)-runInferM info (IM m) =- do counter <- newIORef 0+runInferM info m0 =+ do let IM m = selectorScope m0+ counter <- newIORef 0+ let allPs = inpParams info+ let env = Map.map ExtVar (inpVars info)- <> Map.map (ExtVar . newtypeConType) (inpNewtypes info)+ <> Map.fromList+ [ (ntConName nt, ExtVar (newtypeConType nt))+ | nt <- Map.elems (inpNewtypes info)+ ]+ <> Map.map (ExtVar . mvpType) (mpnFuns allPs) - rec ro <- return RO { iRange = inpRange info+ let ro = RO { iRange = inpRange info , iVars = env+ , iExtModules = inpTopModules info+ , iExtSignatures = inpTopSignatures info , iExtScope = (emptyModule ExternalScope)- { mTySyns = inpTSyns info+ { mTySyns = inpTSyns info <>+ mpnTySyn allPs , mNewtypes = inpNewtypes info , mPrimTypes = inpAbstractTypes info- , mParamTypes = inpParamTypes info- , mParamFuns = inpParamFuns info- , mParamConstraints = inpParamConstraints info+ , mParamTypes = mpnTypes allPs+ , mParamFuns = mpnFuns allPs+ , mParamConstraints = mpnConstraints allPs+ , mSignatures = inpSignatures info } , iTVars = []- , iSolvedHasLazy = iSolvedHas finalRW -- RECURSION+ , iSolvedHasLazy = Map.empty , iMonoBinds = inpMonoBinds info , iCallStacks = inpCallStacks info , iSolver = inpSolver info@@ -145,29 +158,30 @@ , iSolveCounter = counter } - (result, finalRW) <- runStateT rw- $ runReaderT ro m -- RECURSION-- let theSu = iSubst finalRW- defSu = defaultingSubst theSu- warns = fmap' (fmap' (apSubst theSu)) (iWarnings finalRW)+ mb <- runExceptionT (runStateT rw (runReaderT ro m))+ case mb of+ Left errs -> inferFailed [] errs+ Right (result, finalRW) ->+ do let theSu = iSubst finalRW+ defSu = defaultingSubst theSu+ warns = fmap' (fmap' (apSubst theSu)) (iWarnings finalRW) - case iErrors finalRW of- [] ->- case (iCts finalRW, iHasCts finalRW) of- (cts,[])- | nullGoals cts -> inferOk warns- (iNameSeeds finalRW)- (iSupply finalRW)- (apSubst defSu result)- (cts,has) ->- inferFailed warns- [ ( goalRange g- , UnsolvedGoals [apSubst theSu g]- ) | g <- fromGoals cts ++ map hasGoal has- ]+ case iErrors finalRW of+ [] ->+ case iCts finalRW of+ cts+ | nullGoals cts -> inferOk warns+ (iNameSeeds finalRW)+ (iSupply finalRW)+ (apSubst defSu result)+ cts ->+ inferFailed warns+ [ ( goalRange g+ , UnsolvedGoals [apSubst theSu g]+ ) | g <- fromGoals cts+ ] - errs -> inferFailed warns [(r,apSubst theSu e) | (r,e) <- errs]+ errs -> inferFailed warns [(r,apSubst theSu e) | (r,e) <- errs] where inferOk ws a b c = pure (InferOK (computeFreeVarNames ws []) ws a b c)@@ -193,18 +207,70 @@ , iBindTypes = mempty } --+{- | This introduces a new "selector scope" which is currently a module.+I think that it might be possible to have selectors scopes be groups+of recursive declarations instead, as we are not going to learn anything+additional once we are done with the recursive group that generated+the selectors constraints. We do it at the module level because this+allows us to report more errors at once. +A selector scope does the following:+ * Keep track of the Has constraints generated in this scope+ * Keep track of the solutions for discharged selector constraints:+ - this uses a laziness trick where we build up a map containing the+ solutions for the Has constraints in the state+ - the *final* value for this map (i.e., at the value the end of the scope)+ is passed in as thunk in the reader component of the moment+ - as we type check expressions when we need the solution for a Has+ constraint we look it up from the reader environment; note that+ since the map is not yet built up we just get back a thunk, so we have+ to be carefule to not force it until *after* we've solved the goals+ - all of this happens in the `rec` block below+ * At the end of a selector scope we make sure that all Has constraints were+ discharged. If not, we *abort* further type checking. The reason for+ aborting rather than just recording an error is that the expression+ which produce contains thunks that will lead to non-termination if forced,+ and some type-checking operations (e.g., instantiation a functor)+ require us to traverse the expressions.+-}+selectorScope :: InferM a -> InferM a+selectorScope (IM m1) = IM+ do ro <- ask+ rw <- get+ mb <- inBase+ do rec let ro1 = ro { iSolvedHasLazy = solved }+ rw1 = rw { iHasCts = [] : iHasCts rw }+ mb <- runExceptionT (runStateT rw1 (runReaderT ro1 m1))+ let solved = case mb of+ Left {} -> Map.empty+ Right (_,rw2) -> iSolvedHas rw2+ pure mb+ case mb of+ Left err -> raise err+ Right (a,rw1) ->+ case iHasCts rw1 of+ us : cs ->+ do let errs = [ (goalRange g, UnsolvedGoals [g])+ | g <- map hasGoal us ]+ set rw1 { iErrors = errs ++ iErrors rw1, iHasCts = cs }+ unIM (abortIfErrors)+ pure a+ [] -> panic "selectorScope" ["No selector scope"] -newtype InferM a = IM { unIM :: ReaderT RO (StateT RW IO) a }+newtype InferM a = IM { unIM :: ReaderT RO+ ( StateT RW+ ( ExceptionT [(Range,Error)]+ IO+ )) a } data ScopeName = ExternalScope | LocalScope | SubModule Name+ | SignatureScope Name (Maybe Text) -- ^ The Text is docs+ | TopSignatureScope P.ModName | MTopModule P.ModName -- | Read-only component of the monad.@@ -219,10 +285,20 @@ , iTVars :: [TParam] -- ^ Type variable that are in scope + , iExtModules :: ModName -> Maybe (ModuleG (), If.IfaceG ())+ -- ^ An exteral top-level module.+ -- We need the actual module when we instantiate functors,+ -- because currently the type-checker desugars such modules.++ , iExtSignatures :: ModName -> Maybe ModParamNames+ -- ^ External top-level signatures.+ , iExtScope :: ModuleG ScopeName -- ^ These are things we know about, but are not part of the -- modules we are currently constructing. -- XXX: this sould probably be an interface+ -- NOTE: External functors should be looked up in `iExtModules`+ -- and not here, as they may be top-level modules. , iSolvedHasLazy :: Map Int HasGoalSln -- ^ NOTE: This field is lazy in an important way! It is the@@ -274,12 +350,18 @@ -- Constraints that need solving , iCts :: !Goals -- ^ Ordinary constraints- , iHasCts :: ![HasGoal]- {- ^ Tuple/record projection constraints. The 'Int' is the "name"- of the constraint, used so that we can name its solution properly. -}+ , iHasCts :: ![[HasGoal]]+ {- ^ Tuple/record projection constraints. These are separate from+ the other constraints because solving them results in actual elaboration+ of the term, indicating how to do the projection. The modification+ of the term is done using lazyness, by looking up a thunk ahead of time+ (@iSolvedHasLazy@ in RO), which is filled in when the constrait is+ solved (@iSolvedHas@). See also `selectorScope`.+ -} , iScope :: ![ModuleG ScopeName] -- ^ Nested scopes we are currently checking, most nested first.+ -- These are basically partially built modules. , iBindTypes :: !(Map Name Schema) -- ^ Types of variables that we know about. We don't worry about scoping@@ -317,6 +399,7 @@ io :: IO a -> InferM a io m = IM $ inBase m + -- | The monadic computation is about the given range of source code. -- This is useful for error reporting. inRange :: Range -> InferM a -> InferM a@@ -345,7 +428,17 @@ IM $ sets_ $ \s -> s { iErrors = (r,e) : iErrors s } -+-- | If there are any recoded errors than abort firther type-checking.+abortIfErrors :: InferM ()+abortIfErrors =+ do rw <- IM get+ case iErrors rw of+ [] -> pure ()+ es ->+ do es1 <- forM es \(l,e) ->+ do e1 <- applySubst e+ pure (l,e1)+ IM (raise es1) recordWarning :: Warning -> InferM () recordWarning w =@@ -358,7 +451,7 @@ ignore | DefaultingTo d _ <- w , Just n <- tvSourceName (tvarDesc d)- , Declared _ SystemName <- nameInfo n+ , GlobalName SystemName _ <- nameInfo n = True | otherwise = False @@ -443,22 +536,30 @@ newHasGoal l ty f = do goalName <- newGoalName g <- newGoal CtSelector (pHas l ty f)- IM $ sets_ $ \s -> s { iHasCts = HasGoal goalName g : iHasCts s }+ IM $ sets_ \s -> case iHasCts s of+ cs : more ->+ s { iHasCts = (HasGoal goalName g : cs) : more }+ [] -> panic "newHasGoal" ["no selector scope"] solns <- IM $ fmap iSolvedHasLazy ask return $ case Map.lookup goalName solns of Just e1 -> e1 Nothing -> panic "newHasGoal" ["Unsolved has goal in result"] --- | Add a previously generate has constrained+-- | Add a previously generated @Has@ constraint addHasGoal :: HasGoal -> InferM ()-addHasGoal g = IM $ sets_ $ \s -> s { iHasCts = g : iHasCts s }+addHasGoal g = IM $ sets_ \s -> case iHasCts s of+ cs : more -> s { iHasCts = (g : cs) : more }+ [] -> panic "addHasGoal" ["No selector scope"] -- | Get the @Has@ constraints. Each of this should either be solved, -- or added back using 'addHasGoal'. getHasGoals :: InferM [HasGoal]-getHasGoals = do gs <- IM $ sets $ \s -> (iHasCts s, s { iHasCts = [] })- applySubst gs+getHasGoals =+ do gs <- IM $ sets \s -> case iHasCts s of+ cs : more -> (cs, s { iHasCts = [] : more })+ [] -> panic "getHasGoals" ["No selector scope"]+ applySubst gs -- | Specify the solution (@Expr -> Expr@) for the given constraint ('Int'). solveHasGoal :: Int -> HasGoalSln -> InferM ()@@ -469,10 +570,10 @@ -------------------------------------------------------------------------------- -- | Generate a fresh variable name to be used in a local binding.-newParamName :: Namespace -> Ident -> InferM Name-newParamName ns x =+newLocalName :: Namespace -> Ident -> InferM Name+newLocalName ns x = do r <- curRange- liftSupply (mkParameter ns x r)+ liftSupply (mkLocal ns x r) newName :: (NameSeeds -> (a , NameSeeds)) -> InferM a newName upd = IM $ sets $ \s -> let (x,seeds) = upd (iNameSeeds s)@@ -506,7 +607,7 @@ checkParamKind tp flav k = case flav of- TPModParam _ -> return () -- All kinds allowed as module parameters+ TPModParam _ -> starOrHash TPPropSynParam _ -> starOrHashOrProp TPTySynParam _ -> starOrHash TPSchemaParam _ -> starOrHash@@ -547,7 +648,20 @@ checkParamKind tp flav k return tp +-- | Generate a new version of a type parameter. We use this when+-- instantiating module parameters (the "backtick" imports)+freshTParam :: (Name -> TPFlavor) -> TParam -> InferM TParam+freshTParam mkF tp = newName \s ->+ let u = seedTVar s+ in ( tp { tpUnique = u+ , tpFlav = case tpName tp of+ Just n -> mkF (asLocal NSType n)+ Nothing -> tpFlav tp -- shouldn't happen?+ }+ , s { seedTVar = u + 1 }+ ) + -- | Generate an unknown type. The doc is a note about what is this type about. newType :: TypeSource -> Kind -> InferM Type newType src k = TVar `fmap` newTVar src k@@ -635,7 +749,8 @@ case v of ExtVar sch -> getVars sch CurSCC _ t -> getVars t- sels <- IM $ fmap (map (goal . hasGoal) . iHasCts) get+ hasCts <- IM (iHasCts <$> get)+ let sels = map (goal . hasGoal) (concat hasCts) fromSels <- mapM getVars sels fromEx <- (getVars . concatMap Map.elems) =<< IM (fmap iExistTVars get) return (Set.unions fromEnv `Set.union` Set.unions fromSels@@ -656,8 +771,12 @@ do mb1 <- Map.lookup x . iBindTypes <$> IM get case mb1 of Just a -> pure (ExtVar a)- Nothing -> panic "lookupVar" [ "Undefined vairable"- , show x ]+ Nothing ->+ do mp <- IM $ asks iVars+ panic "lookupVar" $ [ "Undefined vairable"+ , show x+ , "IVARS"+ ] ++ map (show . debugShowUniques . pp) (Map.keys mp) -- | Lookup a type variable. Return `Nothing` if there is no such variable -- in scope, in which case we must be dealing with a type constant.@@ -680,10 +799,89 @@ lookupParamType :: Name -> InferM (Maybe ModTParam) lookupParamType x = Map.lookup x <$> getParamTypes --- | Lookup the schema for a parameter function.-lookupParamFun :: Name -> InferM (Maybe ModVParam)-lookupParamFun x = Map.lookup x <$> getParamFuns+lookupSignature :: P.ImpName Name -> InferM ModParamNames+lookupSignature nx =+ case nx of+ -- XXX: top+ P.ImpNested x ->+ do sigs <- getSignatures+ case Map.lookup x sigs of+ Just ips -> pure ips+ Nothing -> panic "lookupSignature"+ [ "Missing signature", show x ] + P.ImpTop t ->+ do loaded <- iExtSignatures <$> IM ask+ case loaded t of+ Just ps -> pure ps+ Nothing -> panic "lookupSignature"+ [ "Top level signature is not loaded", show (pp nx) ]++-- | Lookup an external (i.e., previously loaded) top module.+lookupTopModule :: ModName -> InferM (Maybe (ModuleG (), If.IfaceG ()))+lookupTopModule m =+ do ms <- iExtModules <$> IM ask+ pure (ms m)++lookupFunctor :: P.ImpName Name -> InferM (ModuleG ())+lookupFunctor iname =+ case iname of+ P.ImpTop m -> fst . fromMb <$> lookupTopModule m+ P.ImpNested m ->+ do localFuns <- getScope mFunctors+ case Map.lookup m localFuns of+ Just a -> pure a { mName = () }+ Nothing ->+ do mbTop <- lookupTopModule (nameTopModule m)+ pure (fromMb do a <- fst <$> mbTop+ b <- Map.lookup m (mFunctors a)+ pure b { mName = () })+ where+ fromMb mb = case mb of+ Just a -> a+ Nothing -> panic "lookupFunctor"+ [ "Missing functor", show iname ]+++{- | Get information about the things defined in the module.+Note that, in general, the interface may contain *more* than just the+definitions in the module, however the `ifNames` should indicate which+ones are part of the module.+-}+lookupModule :: P.ImpName Name -> InferM (If.IfaceG ())+lookupModule iname =+ case iname of+ P.ImpTop m -> snd . fromMb <$> lookupTopModule m+ P.ImpNested m ->+ do localMods <- getScope mSubmodules+ case Map.lookup m localMods of+ Just names ->+ do n <- genIfaceWithNames names <$> getCurDecls+ pure (If.ifaceForgetName n)++ Nothing ->+ do mb <- lookupTopModule (nameTopModule m)+ pure (fromMb+ do iface <- snd <$> mb+ names <- Map.lookup m+ (If.ifModules (If.ifDefines iface))+ pure iface+ { If.ifNames = names { If.ifsName = () } })++ where+ fromMb mb = case mb of+ Just a -> a+ Nothing -> panic "lookupModule"+ [ "Missing module", show iname ]++++lookupModParam :: P.Ident -> InferM (Maybe ModParam)+lookupModParam p =+ do scope <- getScope mParams+ pure (Map.lookup p scope)++ -- | Check if we already have a name for this existential type variable and, -- if so, return the definition. If not, try to create a new definition, -- if this is allowed. If not, returns nothing.@@ -717,10 +915,6 @@ getAbstractTypes :: InferM (Map Name AbstractType) getAbstractTypes = getScope mPrimTypes --- | Returns the parameter functions declarations-getParamFuns :: InferM (Map Name ModVParam)-getParamFuns = getScope mParamFuns- -- | Returns the abstract function declarations getParamTypes :: InferM (Map Name ModTParam) getParamTypes = getScope mParamTypes@@ -748,6 +942,11 @@ getCallStacks :: InferM Bool getCallStacks = IM (asks iCallStacks) +getSignatures :: InferM (Map Name ModParamNames)+getSignatures = getScope mSignatures+++ {- | We disallow shadowing between type synonyms and type variables because it is confusing. As a bonus, in the implementation we don't need to worry about where we lookup things (i.e., in the variable or@@ -795,15 +994,28 @@ newLocalScope :: InferM () newLocalScope = newScope LocalScope -newSubmoduleScope :: Name -> [Import] -> ExportSpec Name -> InferM ()-newSubmoduleScope x is e =- do newScope (SubModule x)- updScope \m -> m { mImports = is, mExports = e }+newSignatureScope :: Name -> Maybe Text -> InferM ()+newSignatureScope x doc =+ do updScope \o -> o { mNested = Set.insert x (mNested o) }+ newScope (SignatureScope x doc) -newModuleScope :: P.ModName -> [Import] -> ExportSpec Name -> InferM ()-newModuleScope x is e =+newTopSignatureScope :: ModName -> InferM ()+newTopSignatureScope x = newScope (TopSignatureScope x)++{- | Start a new submodule scope. The imports and exports are just used+to initialize an empty module. As we type check declarations they are+added to this module's scope. -}+newSubmoduleScope ::+ Name -> Maybe Text -> ExportSpec Name -> InferM ()+newSubmoduleScope x docs e =+ do updScope \o -> o { mNested = Set.insert x (mNested o) }+ newScope (SubModule x)+ updScope \m -> m { mDoc = docs, mExports = e }++newModuleScope :: P.ModName -> ExportSpec Name -> InferM ()+newModuleScope x e = do newScope (MTopModule x)- updScope \m -> m { mImports = is, mExports = e }+ updScope \m -> m { mDoc = Nothing, mExports = e } -- | Update the current scope (first in the list). Assumes there is one. updScope :: (ModuleG ScopeName -> ModuleG ScopeName) -> InferM ()@@ -829,40 +1041,85 @@ case iScope rw of x@Module { mName = SubModule m } : y : more -> rw { iScope = z : more } where- x1 = x { mName = m }- iface = genIface x1- me = if isParametrizedModule x1 then Map.singleton m x1 else mempty- z = y { mImports = mImports x ++ mImports y -- just for deps- , mSubModules = Map.insert m iface (mSubModules y)+ x1 = x { mName = m, mDecls = reverse (mDecls x) } - , mTySyns = mTySyns x <> mTySyns y- , mNewtypes = mNewtypes x <> mNewtypes y- , mPrimTypes = mPrimTypes x <> mPrimTypes y- , mDecls = mDecls x <> mDecls y- , mFunctors = me <> mFunctors x <> mFunctors y+ isFun = isParametrizedModule x1++ add :: Monoid a => (ModuleG ScopeName -> a) -> a+ add f = if isFun then f y else f x <> f y++ z = Module+ { mName = mName y+ , mDoc = mDoc y+ , mExports = mExports y+ , mParamTypes = mParamTypes y+ , mParamFuns = mParamFuns y+ , mParamConstraints = mParamConstraints y+ , mParams = mParams y+ , mNested = mNested y++ , mTySyns = add mTySyns+ , mNewtypes = add mNewtypes+ , mPrimTypes = add mPrimTypes+ , mDecls = add mDecls+ , mSignatures = add mSignatures+ , mSubmodules = if isFun+ then mSubmodules y+ else Map.insert m (genIfaceNames x1)+ (mSubmodules x <> mSubmodules y)+ , mFunctors = if isFun+ then Map.insert m x1 (mFunctors y)+ else mFunctors x <> mFunctors y } _ -> panic "endSubmodule" [ "Not a submodule" ] -endModule :: InferM Module+endModule :: InferM TCTopEntity endModule = IM $ sets \rw -> case iScope rw of [ x ] | MTopModule m <- mName x ->- ( x { mName = m, mDecls = reverse (mDecls x) }+ ( TCTopModule x { mName = m, mDecls = reverse (mDecls x) } , rw { iScope = [] } ) _ -> panic "endModule" [ "Not a single top module" ] -endModuleInstance :: InferM ()-endModuleInstance =+endSignature :: InferM ()+endSignature = IM $ sets_ \rw -> case iScope rw of- [ x ] | MTopModule _ <- mName x -> rw { iScope = [] }- _ -> panic "endModuleInstance" [ "Not single top module" ]+ x@Module { mName = SignatureScope m doc } : y : more ->+ rw { iScope = z : more }+ where+ z = y { mSignatures = Map.insert m sig (mSignatures y) }+ sig = ModParamNames+ { mpnTypes = mParamTypes x+ , mpnConstraints = mParamConstraints x+ , mpnFuns = mParamFuns x+ , mpnTySyn = mTySyns x+ , mpnDoc = doc+ }+ _ -> panic "endSignature" [ "Not a signature scope" ] +endTopSignature :: InferM TCTopEntity+endTopSignature =+ IM $ sets \rw ->+ case iScope rw of+ [ x ] | TopSignatureScope m <- mName x ->+ ( TCTopSignature m ModParamNames+ { mpnTypes = mParamTypes x+ , mpnConstraints = mParamConstraints x+ , mpnFuns = mParamFuns x+ , mpnTySyn = mTySyns x+ , mpnDoc = Nothing+ }+ , rw { iScope = [] }+ )+ _ -> panic "endTopSignature" [ "Not a top-level signature" ] ++ -- | Get an environment combining all nested scopes. getScope :: Semigroup a => (ModuleG ScopeName -> a) -> InferM a getScope f =@@ -870,6 +1127,39 @@ rw <- IM get pure (sconcat (f (iExtScope ro) :| map f (iScope rw))) +getCurDecls :: InferM (ModuleG ())+getCurDecls =+ do ro <- IM ask+ rw <- IM get+ pure (foldr (\m1 m2 -> mergeDecls (forget m1) m2)+ (forget (iExtScope ro)) (iScope rw))++ where+ forget m = m { mName = () }++ mergeDecls m1 m2 =+ Module+ { mName = ()+ , mDoc = Nothing+ , mExports = mempty+ , mParams = mempty+ , mParamTypes = mempty+ , mParamConstraints = mempty+ , mParamFuns = mempty+ , mNested = mempty++ , mTySyns = uni mTySyns+ , mNewtypes = uni mNewtypes+ , mPrimTypes = uni mPrimTypes+ , mDecls = uni mDecls+ , mSubmodules = uni mSubmodules+ , mFunctors = uni mFunctors+ , mSignatures = uni mSignatures+ }+ where+ uni f = f m1 <> f m2++ addDecls :: DeclGroup -> InferM () addDecls ds = do updScope \r -> r { mDecls = ds : mDecls r }@@ -888,7 +1178,7 @@ addNewtype :: Newtype -> InferM () addNewtype t = do updScope \r -> r { mNewtypes = Map.insert (ntName t) t (mNewtypes r) }- IM $ sets_ \rw -> rw { iBindTypes = Map.insert (ntName t)+ IM $ sets_ \rw -> rw { iBindTypes = Map.insert (ntConName t) (newtypeConType t) (iBindTypes rw) } @@ -897,10 +1187,26 @@ updScope \r -> r { mPrimTypes = Map.insert (atName t) t (mPrimTypes r) } + addParamType :: ModTParam -> InferM () addParamType a = updScope \r -> r { mParamTypes = Map.insert (mtpName a) a (mParamTypes r) } +addSignatures :: Map Name ModParamNames -> InferM ()+addSignatures mp =+ updScope \r -> r { mSignatures = Map.union mp (mSignatures r) }++addSubmodules :: Map Name (If.IfaceNames Name) -> InferM ()+addSubmodules mp =+ updScope \r -> r { mSubmodules = Map.union mp (mSubmodules r) }++addFunctors :: Map Name (ModuleG Name) -> InferM ()+addFunctors mp =+ updScope \r -> r { mFunctors = Map.union mp (mFunctors r) }++++ -- | The sub-computation is performed with the given abstract function in scope. addParamFun :: ModVParam -> InferM () addParamFun x =@@ -912,6 +1218,10 @@ addParameterConstraints :: [Located Prop] -> InferM () addParameterConstraints ps = updScope \r -> r { mParamConstraints = ps ++ mParamConstraints r }++addModParam :: ModParam -> InferM ()+addModParam p =+ updScope \r -> r { mParams = Map.insert (mpName p) p (mParams r) }
src/Cryptol/TypeCheck/Parseable.hs view
@@ -63,6 +63,8 @@ --NOTE: erase all "proofs" for now (change the following two lines to change that) showParseable (EProofAbs {-p-}_ e) = showParseable e --"(EProofAbs " ++ show p ++ showParseable e ++ ")" showParseable (EProofApp e) = showParseable e --"(EProofApp " ++ showParseable e ++ ")"+ + showParseable (EPropGuards guards _) = parens (text "EPropGuards" $$ showParseable guards) instance (ShowParseable a, ShowParseable b) => ShowParseable (a,b) where showParseable (x,y) = parens (showParseable x <> comma <> showParseable y)@@ -93,6 +95,7 @@ instance ShowParseable DeclDef where showParseable DPrim = text (show DPrim)+ showParseable (DForeign t) = text (show $ DForeign t) showParseable (DExpr e) = parens (text "DExpr" $$ showParseable e) instance ShowParseable DeclGroup where
src/Cryptol/TypeCheck/Sanity.hs view
@@ -5,12 +5,15 @@ -- Maintainer : cryptol@galois.com -- Stability : provisional -- Portability : portable+{-# Language OverloadedStrings #-} module Cryptol.TypeCheck.Sanity ( tcExpr , tcDecls , tcModule , ProofObligation+ , onlyNonTrivial , Error(..)+ , AreSame(..) , same ) where @@ -19,8 +22,10 @@ import Cryptol.TypeCheck.AST import Cryptol.TypeCheck.Subst (apSubst, singleTParamSubst) import Cryptol.TypeCheck.Monad(InferInput(..))+import Cryptol.ModuleSystem.Name(nameLoc) import Cryptol.Utils.Ident import Cryptol.Utils.RecordMap+import Cryptol.Utils.PP import Data.List (sort) import qualified Data.Set as Set@@ -48,7 +53,21 @@ k2 = withVars (Map.toList (fmap mvpType (mParamFuns m))) $ checkDecls (mDecls m) +onlyNonTrivial :: [ProofObligation] -> [ProofObligation]+onlyNonTrivial = filter (not . trivialProofObligation) +-- | Identify proof obligations that are obviously true.+-- We can filter these to avoid clutter+trivialProofObligation :: ProofObligation -> Bool+trivialProofObligation oblig = pIsTrue goal || simpleEq || goal `elem` asmps+ where+ goal = sType oblig+ asmps = sProps oblig+ simpleEq = case pIsEqual goal of+ Just (t1,t2) -> t1 == t2+ Nothing -> False++ -------------------------------------------------------------------------------- checkDecls :: [DeclGroup] -> TcM ()@@ -107,23 +126,68 @@ where check = do mapM_ (checkTypeIs KProp) ps checkTypeIs KType t +data AreSame = SameIf [Prop]+ | NotSame +areSame :: AreSame+areSame = SameIf []++sameAnd :: AreSame -> AreSame -> AreSame+sameAnd x y =+ case (x,y) of+ (SameIf xs, SameIf ys) -> SameIf (xs ++ ys)+ _ -> NotSame++sameBool :: Bool -> AreSame+sameBool b = if b then areSame else NotSame++sameTypes :: String -> Type -> Type -> TcM ()+sameTypes msg x y = sameSchemas msg (tMono x) (tMono y)++sameSchemas :: String -> Schema -> Schema -> TcM ()+sameSchemas msg x y =+ case same x y of+ NotSame -> reportError (TypeMismatch msg x y)+ SameIf ps -> mapM_ proofObligation ps++++ class Same a where- same :: a -> a -> Bool+ same :: a -> a -> AreSame instance Same a => Same [a] where- same [] [] = True- same (x : xs) (y : ys) = same x y && same xs ys- same _ _ = False+ same [] [] = areSame+ same (x : xs) (y : ys) = same x y `sameAnd` same xs ys+ same _ _ = NotSame +data Field a b = Field a b++instance (Eq a, Same b) => Same (Field a b) where+ same (Field x a) (Field y b) = sameBool (x == y) `sameAnd` same a b+ instance Same Type where- same t1 t2 = tNoUser t1 == tNoUser t2+ same t1 t2+ | k1 /= k2 = NotSame+ | k1 == KNum = if t1 == t2 then SameIf [] else SameIf [ t1 =#= t2 ]+ | otherwise =+ case (tNoUser t1, tNoUser t2) of+ (TVar x, TVar y) -> sameBool (x == y)+ (TRec x, TRec y) -> same (mkRec x) (mkRec y)+ (TNewtype x xs, TNewtype y ys) -> same (Field x xs) (Field y ys)+ (TCon x xs, TCon y ys) -> same (Field x xs) (Field y ys)+ _ -> NotSame+ where+ k1 = kindOf t1+ k2 = kindOf t2+ mkRec r = [ Field x y | (x,y) <- canonicalFields r ] instance Same Schema where- same (Forall xs ps s) (Forall ys qs t) = same xs ys && same ps qs && same s t+ same (Forall xs ps s) (Forall ys qs t) =+ same xs ys `sameAnd` same ps qs `sameAnd` same s t instance Same TParam where- same x y = tpName x == tpName y && tpKind x == tpKind y+ same x y = sameBool (tpName x == tpName y && tpKind x == tpKind y) @@ -153,8 +217,7 @@ do checkTypeIs KType t forM_ es $ \e -> do t1 <- exprType e- unless (same t1 t) $- reportError $ TypeMismatch "EList" (tMono t) (tMono t1)+ sameTypes "EList" t1 t return $ tMono $ tSeq (tNum (length es)) t @@ -169,9 +232,7 @@ do ty <- exprType e expe <- checkHas ty x has <- exprType v- unless (same expe has) $- reportError $- TypeMismatch "ESet" (tMono expe) (tMono has)+ sameTypes "ESet" expe has return (tMono ty) ESel e sel -> do ty <- exprType e@@ -180,13 +241,11 @@ EIf e1 e2 e3 -> do ty <- exprType e1- unless (same tBit ty) $- reportError $ TypeMismatch "EIf_condition" (tMono tBit) (tMono ty)+ sameTypes "EIf_condition" tBit ty t1 <- exprType e2 t2 <- exprType e3- unless (same t1 t2) $- reportError $ TypeMismatch "EIf_arms" (tMono t1) (tMono t2)+ sameTypes "EIf_arms" t1 t2 return $ tMono t1 @@ -238,7 +297,9 @@ case tNoUser t1 of TCon (TC TCFun) [ a, b ]- | same a t2 -> return (tMono b)+ | SameIf ps <- same a t2 ->+ do mapM_ proofObligation ps+ return (tMono b) tf -> reportError (BadApplication tf t1) @@ -270,6 +331,9 @@ in go dgs + EPropGuards _guards typ -> + pure Forall {sVars = [], sProps = [], sType = typ}+ checkHas :: Type -> Selector -> TcM Type checkHas t sel = case sel of@@ -398,12 +462,19 @@ do when checkSig $ checkSchema $ dSignature d return (dName d, dSignature d) + DForeign _ ->+ do when checkSig $ checkSchema $ dSignature d+ return (dName d, dSignature d)+ DExpr e -> do let s = dSignature d when checkSig $ checkSchema s s1 <- exprSchema e- unless (same s s1) $- reportError $ TypeMismatch "DExpr" s s1+ let nm = dName d+ loc = "definition of " ++ show (pp nm) +++ ", at " ++ show (pp (nameLoc nm))+ sameSchemas loc s s1+ return (dName d, s) checkDeclGroup :: DeclGroup -> TcM [(Name, Schema)]@@ -427,7 +498,9 @@ t1 <- exprType e case tNoUser t1 of TCon (TC TCSeq) [ l, el ]- | same elt el -> return ((x, tMono elt), l)+ | SameIf ps <- same elt el ->+ do mapM_ proofObligation ps+ return ((x, tMono elt), l) | otherwise -> reportError $ TypeMismatch "From" (tMono elt) (tMono el) @@ -487,13 +560,15 @@ (Left err, _) -> Left err (Right a, s) -> Right (a, woProofObligations s) where+ allPs = inpParams env+ ro = RO { roTVars = Map.fromList [ (tpUnique x, x)- | tp <- Map.elems (inpParamTypes env)+ | tp <- Map.elems (mpnTypes allPs) , let x = mtpParam tp ]- , roAsmps = map thing (inpParamConstraints env)+ , roAsmps = map thing (mpnConstraints allPs) , roRange = emptyRange , roVars = Map.union- (fmap mvpType (inpParamFuns env))+ (fmap mvpType (mpnFuns allPs)) (inpVars env) } rw = RW { woProofObligations = [] }@@ -579,3 +654,114 @@ case Map.lookup x (roVars ro) of Just s -> return s Nothing -> reportError $ UndefinedVariable x+++instance PP Error where+ ppPrec _ err =+ case err of++ TypeMismatch what expected actual ->+ ppErr ("Type mismatch in" <+> text what)+ [ "Expected:" <+> pp expected+ , "Actual :" <+> pp actual+ ]++ ExpectedMono s ->+ ppErr "Not a monomorphic type"+ [ pp s ]++ TupleSelectorOutOfRange sel sz ->+ ppErr "Tuple selector out of range"+ [ "Selector:" <+> int sel+ , "Size :" <+> int sz+ ]++ MissingField f fs ->+ ppErr "Invalid record selector"+ [ "Field: " <+> pp f+ , "Fields:" <+> commaSep (map pp fs)+ ]++ UnexpectedTupleShape expected actual ->+ ppErr "Unexpected tuple shape"+ [ "Expected:" <+> int expected+ , "Actual :" <+> int actual+ ]++ UnexpectedRecordShape expected actual ->+ ppErr "Unexpected record shape"+ [ "Expected:" <+> commaSep (map pp expected)+ , "Actual :" <+> commaSep (map pp actual)+ ]++ UnexpectedSequenceShape n t ->+ ppErr "Unexpected sequence shape"+ [ "Expected:" <+> int n+ , "Actual :" <+> pp t+ ]++ BadSelector sel t ->+ ppErr "Bad selector"+ [ "Selector:" <+> pp sel+ , "Type :" <+> pp t+ ]++ BadInstantiation ->+ ppErr "Bad instantiation" []++ Captured x ->+ ppErr "Captured type variable"+ [ "Variable:" <+> pp x ]++ BadProofNoAbs ->+ ppErr "Proof application without a proof abstraction" []++ BadProofTyVars xs ->+ ppErr "Proof application with type abstraction"+ [ "Type parameter:" <+> pp x | x <- xs ]++ KindMismatch expected actual ->+ ppErr "Kind mismatch"+ [ "Expected:" <+> pp expected+ , "Actual :" <+> pp actual+ ]++ NotEnoughArgumentsInKind k ->+ ppErr "Not enough arguments in kind" [ pp k ]++ BadApplication t1 t2 ->+ ppErr "Bad application"+ [ "Function:" <+> pp t1+ , "Argument:" <+> pp t2+ ]++ FreeTypeVariable x ->+ ppErr "Free type variable"+ [ "Variable:" <+> pp x ]++ BadTypeApplication kf ka ->+ ppErr "Bad type application"+ [ "Function :" <+> pp kf+ , "Arguments:" <+> commaSep (map pp ka)+ ]++ RepeatedVariableInForall x ->+ ppErr "Repeated variable in forall"+ [ "Variable:" <+> pp x ]++ BadMatch t ->+ ppErr "Bad match"+ [ "Type:" <+> pp t ]++ EmptyArm -> ppErr "Empty comprehension arm" []++ UndefinedTypeVaraible x ->+ ppErr "Undefined type variable"+ [ "Variable:" <+> pp x ]++ UndefinedVariable x ->+ ppErr "Undefined variable"+ [ "Variable:" <+> pp x ]++ where+ ppErr x ys = hang x 2 (vcat [ "•" <+> y | y <- ys ])
src/Cryptol/TypeCheck/SimpType.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE PatternGuards #-}+{-# LANGUAGE Safe #-} -- See Note [-Wincomplete-uni-patterns and irrefutable patterns] in Cryptol.TypeCheck.TypePat {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Cryptol.TypeCheck.SimpType where
src/Cryptol/TypeCheck/Solve.hs view
@@ -7,10 +7,10 @@ -- Portability : portable {-# LANGUAGE PatternGuards, BangPatterns, RecordWildCards #-}-{-# LANGUAGE Safe #-} module Cryptol.TypeCheck.Solve ( simplifyAllConstraints , proveImplication+ , tryProveImplication , proveModuleTopLevel , defaultAndSimplify , defaultReplExpr@@ -37,6 +37,7 @@ import Control.Applicative ((<|>)) import Control.Monad(mzero)+import Data.Containers.ListUtils (nubOrd) import Data.Map (Map) import qualified Data.Map as Map import Data.Set ( Set )@@ -265,28 +266,49 @@ cs <- getParamConstraints case cs of [] -> addGoals gs1- _ -> do su2 <- proveImplication Nothing [] [] gs1+ _ -> do su2 <- proveImplication False Nothing [] [] gs1 extendSubst su2 -- | Prove an implication, and return any improvements that we computed. -- Records errors, if any of the goals couldn't be solved.-proveImplication :: Maybe Name -> [TParam] -> [Prop] -> [Goal] -> InferM Subst-proveImplication lnam as ps gs =+proveImplication :: Bool -> Maybe Name ->+ [TParam] -> [Prop] -> [Goal] -> InferM Subst+proveImplication dedupErrs lnam as ps gs = do evars <- varsWithAsmps solver <- getSolver extraAs <- (map mtpParam . Map.elems) <$> getParamTypes extra <- map thing <$> getParamConstraints - (mbErr,su) <- io (proveImplicationIO solver lnam evars+ (mbErr,su) <- io (proveImplicationIO solver dedupErrs lnam evars (extraAs ++ as) (extra ++ ps) gs) case mbErr of Right ws -> mapM_ recordWarning ws Left errs -> mapM_ recordError errs return su +-- | Tries to prove an implication. If proved, then returns `Right (m_su ::+-- InferM Subst)` where `m_su` is an `InferM` computation that results in the+-- solution substitution, and records any warning invoked during proving. If not+-- proved, then returns `Left (m_err :: InferM ())`, which records all errors+-- invoked during proving.+tryProveImplication :: + Maybe Name -> [TParam] -> [Prop] -> [Goal] -> InferM Bool+tryProveImplication lnam as ps gs =+ do evars <- varsWithAsmps+ solver <- getSolver + extraAs <- (map mtpParam . Map.elems) <$> getParamTypes+ extra <- map thing <$> getParamConstraints++ (mbErr,_su) <- io (proveImplicationIO solver False lnam evars+ (extraAs ++ as) (extra ++ ps) gs)+ case mbErr of+ Left {} -> pure False+ Right {} -> pure True+ proveImplicationIO :: Solver+ -> Bool -- ^ Whether to remove duplicate goals in errors -> Maybe Name -- ^ Checking this function -> Set TVar -- ^ These appear in the env., and we should -- not try to default them@@ -294,8 +316,8 @@ -> [Prop] -- ^ Assumed constraint -> [Goal] -- ^ Collected constraints -> IO (Either [Error] [Warning], Subst)-proveImplicationIO _ _ _ _ [] [] = return (Right [], emptySubst)-proveImplicationIO s f varsInEnv ps asmps0 gs0 =+proveImplicationIO _ _ _ _ _ [] [] = return (Right [], emptySubst)+proveImplicationIO s dedupErrs f varsInEnv ps asmps0 gs0 = do let ctxt = buildSolverCtxt asmps res <- quickSolverIO ctxt gs case res of@@ -315,7 +337,7 @@ return (Left (err gs3:errs), su) -- XXX: Old? (_,newGs,newSu,ws,errs) -> do let su1 = newSu @@ su- (res1,su2) <- proveImplicationIO s f varsInEnv ps+ (res1,su2) <- proveImplicationIO s dedupErrs f varsInEnv ps (apSubst su1 asmps0) newGs let su3 = su2 @@ su1 case res1 of@@ -329,7 +351,7 @@ $ DelayedCt { dctSource = f , dctForall = ps , dctAsmps = asmps0- , dctGoals = us+ , dctGoals = if dedupErrs then nubOrd us else us }
src/Cryptol/TypeCheck/Solver/Class.hs view
@@ -7,6 +7,7 @@ -- Portability : portable -- -- Solving class constraints.+-- If you make changes to this file, please update the documenation in RefMan.md {-# LANGUAGE PatternGuards #-} module Cryptol.TypeCheck.Solver.Class
src/Cryptol/TypeCheck/Solver/Improve.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE Safe #-}+ -- | Look for opportunity to solve goals by instantiating variables. module Cryptol.TypeCheck.Solver.Improve where
src/Cryptol/TypeCheck/Solver/Numeric/Interval.hs view
@@ -10,11 +10,13 @@ {-# LANGUAGE PatternGuards #-} {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE Safe #-} module Cryptol.TypeCheck.Solver.Numeric.Interval where import Cryptol.TypeCheck.AST import Cryptol.TypeCheck.Solver.InfNat+import Cryptol.TypeCheck.PP(NameMap,ppWithNames) import Cryptol.Utils.PP hiding (int) import Data.Map ( Map )@@ -162,6 +164,14 @@ ppIntervals = vcat . map ppr . Map.toList where ppr (var,i) = pp var <.> char ':' <+> ppInterval i++ppIntervalsWithNames :: NameMap -> Map TVar Interval -> Doc+ppIntervalsWithNames nms = vcat . map ppr . Map.toList+ where+ ppr :: (TVar,Interval) -> Doc+ ppr (var,i) = ppWithNames nms var <.> char ':' <+> ppInterval i++ ppInterval :: Interval -> Doc ppInterval x = brackets (hsep [ ppr (iLower x)
src/Cryptol/TypeCheck/Solver/SMT.hs view
@@ -10,7 +10,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# Language FlexibleInstances #-} {-# LANGUAGE PatternGuards #-}-{-# LANGUAGE TypeSynonymInstances #-} module Cryptol.TypeCheck.Solver.SMT ( -- * Setup@@ -31,6 +30,9 @@ , checkUnsolvable , tryGetModel , shrinkModel++ -- * Lower level interactions+ , inNewFrame, TVars, declareVars, assume, unsolvable ) where import SimpleSMT (SExpr)@@ -187,9 +189,6 @@ -------------------------------------------------------------------------------- --- -- | Returns goals that were not proved proveImp :: Solver -> [Prop] -> [Goal] -> IO [Goal] proveImp sol ps gs0 =@@ -288,13 +287,26 @@ pop :: Solver -> IO () pop sol = SMT.pop (solver sol) +inNewFrame :: Solver -> IO a -> IO a+inNewFrame sol m =+ do push sol+ a <- m+ pop sol+ pure a + declareVar :: Solver -> Int -> TVar -> IO (TVar, SExpr) declareVar s x v = do let name = (if isFreeTV v then "fv" else "kv") ++ show x e <- SMT.declare (solver s) name cryInfNat SMT.assert (solver s) (SMT.fun "cryVar" [ e ]) return (v,e)+++declareVars :: Solver -> [TVar] -> IO TVars+declareVars sol vs =+ Map.fromList <$> zipWithM (declareVar sol) [ 0 .. ]+ [ v | v <- vs, kindOf v == KNum ] assume :: Solver -> TVars -> Prop -> IO () assume s tvs p = SMT.assert (solver s) (SMT.fun "cryAssume" [ toSMT tvs p ])
src/Cryptol/TypeCheck/Solver/Selector.hs view
@@ -5,7 +5,7 @@ -- Maintainer : cryptol@galois.com -- Stability : provisional -- Portability : portable-{-# LANGUAGE PatternGuards, Safe #-}+{-# LANGUAGE PatternGuards #-} module Cryptol.TypeCheck.Solver.Selector (tryHasGoal) where import Cryptol.Parser.Position(Range)@@ -13,7 +13,7 @@ import Cryptol.TypeCheck.InferTypes import Cryptol.TypeCheck.Monad( InferM, unify, newGoals , newType, applySubst, solveHasGoal- , newParamName+ , newLocalName ) import Cryptol.TypeCheck.Subst (listParamSubst, apSubst) import Cryptol.Utils.Ident (Ident, packIdent,Namespace(..))@@ -166,9 +166,9 @@ -- xs.s ~~> [ x.s | x <- xs ] -- { xs | s = ys } ~~> [ { x | s = y } | x <- xs | y <- ys ] liftSeq len el =- do x1 <- newParamName NSValue (packIdent "x")- x2 <- newParamName NSValue (packIdent "x")- y2 <- newParamName NSValue (packIdent "y")+ do x1 <- newLocalName NSValue (packIdent "x")+ x2 <- newLocalName NSValue (packIdent "x")+ y2 <- newLocalName NSValue (packIdent "y") case tNoUser innerT of TCon _ [_,eli] -> do d <- mkSelSln s el eli@@ -190,8 +190,8 @@ -- f.s ~~> \x -> (f x).s -- { f | s = g } ~~> \x -> { f x | s = g x } liftFun t1 t2 =- do x1 <- newParamName NSValue (packIdent "x")- x2 <- newParamName NSValue (packIdent "x")+ do x1 <- newLocalName NSValue (packIdent "x")+ x2 <- newLocalName NSValue (packIdent "x") case tNoUser innerT of TCon _ [_,inT] -> do d <- mkSelSln s t2 inT
src/Cryptol/TypeCheck/Solver/Types.hs view
@@ -1,4 +1,5 @@ {-# Language OverloadedStrings, DeriveGeneric, DeriveAnyClass #-}+{-# LANGUAGE Safe #-} module Cryptol.TypeCheck.Solver.Types where import Data.Map(Map)
src/Cryptol/TypeCheck/Subst.hs view
@@ -7,10 +7,7 @@ -- Portability : portable {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-}@@ -35,6 +32,7 @@ , applySubstToVar , substToList , fmap', (!$), (.$)+ , mergeDistinctSubst ) where import Data.Maybe@@ -85,6 +83,29 @@ , suDefaulting = False } +mergeDistinctSubst :: [Subst] -> Subst+mergeDistinctSubst sus =+ case sus of+ [] -> emptySubst+ _ -> foldr1 merge sus++ where+ merge s1 s2 = S { suFreeMap = jn suFreeMap s1 s2+ , suBoundMap = jn suBoundMap s1 s2+ , suDefaulting = if suDefaulting s1 || suDefaulting s2+ then err+ else False+ }++ err = panic "mergeDistinctSubst" [ "Not distinct" ]+ bad _ _ = err+ jn f x y = IntMap.unionWith bad (f x) (f y)++++++ -- | Reasons to reject a single-variable substitution. data SubstError = SubstRecursive@@ -241,7 +262,15 @@ Just (TUser f ts1 t1) TRec fs -> TRec `fmap` (anyJust (apSubstMaybe su) fs)- TNewtype nt ts -> TNewtype nt `fmap` anyJust (apSubstMaybe su) ts++ {- We apply the substitution to the newtype as well, because it might+ contain module parameters, which need to be substituted when+ instantiating a functor. -}+ TNewtype nt ts ->+ uncurry TNewtype <$> anyJust2 (applySubstToNewtype su)+ (anyJust (apSubstMaybe su))+ (nt,ts)+ TVar x -> applySubstToVar su x lookupSubst :: TVar -> Subst -> Maybe Type@@ -263,6 +292,16 @@ | suDefaulting su -> Just $! defaultFreeVar x | otherwise -> Nothing ++applySubstToNewtype :: Subst -> Newtype -> Maybe Newtype+applySubstToNewtype su nt =+ do (cs,fs) <- anyJust2+ (anyJust (apSubstMaybe su))+ (anyJust (apSubstMaybe su))+ (ntConstraints nt, ntFields nt)+ pure nt { ntConstraints = cs, ntFields = fs }++ class TVars t where apSubst :: Subst -> t -> t -- ^ Replaces free variables. To prevent space leaks when used with@@ -351,7 +390,16 @@ instance TVars Schema where apSubst su (Forall xs ps t) =- Forall xs !$ (concatMap pSplitAnd (apSubst su ps)) !$ (apSubst su t)+ Forall xs !$ (map doProp ps) !$ (apSubst su t)+ where+ doProp = pAnd . pSplitAnd . apSubst su+ {- NOTE: when applying a substitution to the predicates of a schema+ we preserve the number of predicate, even if some of them became+ "True" or and "And". This is to accomodate applying substitution+ to already type checked code (e.g., when instantiating a functor)+ where the predictes in the schema need to match the corresponding+ EProofAbs in the term.+ -} instance TVars Expr where apSubst su = go@@ -363,20 +411,16 @@ EAbs x t e1 -> EAbs x !$ (apSubst su t) !$ (go e1) ETAbs a e -> ETAbs a !$ (go e) ETApp e t -> ETApp !$ (go e) !$ (apSubst su t)- EProofAbs p e -> EProofAbs !$ hmm !$ (go e)- where hmm = case pSplitAnd (apSubst su p) of- [p1] -> p1- res -> panic "apSubst@EProofAbs"- [ "Predicate split or disappeared after"- , "we applied a substitution."- , "Predicate:"- , show (pp p)- , "Became:"- , show (map pp res)- , "subst:"- , show (pp su)- ]+ EProofAbs p e -> EProofAbs !$ p' !$ (go e)+ where p' = pAnd (pSplitAnd (apSubst su p))+ {- NOTE: we used to panic if `pSplitAnd` didn't return a single result.+ It is useful to avoid the panic if applying the substitution to+ already type checked code (e.g., when we are instantitaing a+ functor). In that case, we don't have the option to modify the+ `EProofAbs` because we'd have to change all call sites, but things might+ simplify because of the extra info in the substitution. -} + EProofApp e -> EProofApp !$ (go e) EVar {} -> expr@@ -391,6 +435,8 @@ EWhere e ds -> EWhere !$ (go e) !$ (apSubst su ds) + EPropGuards guards ty -> EPropGuards !$ (\(props, e) -> (apSubst su `fmap'` props, apSubst su e)) `fmap'` guards .$ ty+ instance TVars Match where apSubst su (From x len t e) = From x !$ (apSubst su len) !$ (apSubst su t) !$ (apSubst su e) apSubst su (Let b) = Let !$ (apSubst su b)@@ -401,15 +447,25 @@ instance TVars Decl where apSubst su d =- let !sig' = id $! apSubst su (dSignature d)+ let !sig' = apSubst su (dSignature d) !def' = apSubst su (dDefinition d) in d { dSignature = sig', dDefinition = def' } instance TVars DeclDef where- apSubst su (DExpr e) = DExpr !$ (apSubst su e)- apSubst _ DPrim = DPrim+ apSubst su (DExpr e) = DExpr !$ (apSubst su e)+ apSubst _ DPrim = DPrim+ apSubst _ (DForeign t) = DForeign t -instance TVars Module where+-- WARNING: This applies the substitution only to the declarations.+instance TVars (ModuleG names) where apSubst su m = let !decls' = apSubst su (mDecls m)- in m { mDecls = decls' }+ !funs' = apSubst su <$> mFunctors m+ in m { mDecls = decls', mFunctors = funs' }++-- WARNING: This applies the substitution only to the declarations in modules.+instance TVars TCTopEntity where+ apSubst su ent =+ case ent of+ TCTopModule m -> TCTopModule (apSubst su m)+ TCTopSignature {} -> ent
src/Cryptol/TypeCheck/TCon.hs view
@@ -40,7 +40,7 @@ builtInType :: M.Name -> Maybe TCon builtInType nm = case M.nameInfo nm of- M.Declared m _+ M.GlobalName _ OrigName { ogModule = m } | m == M.TopModule preludeName -> Map.lookup (M.nameIdent nm) builtInTypes | m == M.TopModule floatName -> Map.lookup (M.nameIdent nm) builtInFloat | m == M.TopModule arrayName -> Map.lookup (M.nameIdent nm) builtInArray
src/Cryptol/TypeCheck/Type.hs view
@@ -16,6 +16,8 @@ import GHC.Generics (Generic) import Control.DeepSeq +import Data.Map(Map)+import qualified Data.Map as Map import qualified Data.IntMap as IntMap import Data.Maybe (fromMaybe) import Data.Set (Set)@@ -23,9 +25,10 @@ import Data.Text (Text) import Cryptol.Parser.Selector-import Cryptol.Parser.Position(Range,emptyRange)+import Cryptol.Parser.Position(Located,thing,Range,emptyRange)+import Cryptol.Parser.AST(ImpName(..)) import Cryptol.ModuleSystem.Name-import Cryptol.Utils.Ident (Ident, isInfixIdent, exprModName)+import Cryptol.Utils.Ident (Ident, isInfixIdent, exprModName, ogModule, ModName) import Cryptol.TypeCheck.TCon import Cryptol.TypeCheck.PP import Cryptol.TypeCheck.Solver.InfNat@@ -37,18 +40,75 @@ infix 4 =#=, >== infixr 5 `tFun` ++--------------------------------------------------------------------------------+-- Module parameters++type FunctorParams = Map Ident ModParam++-- | Compute the names from all functor parameters+allParamNames :: FunctorParams -> ModParamNames+allParamNames mps =+ ModParamNames+ { mpnTypes = Map.unions (map mpnTypes ps)+ , mpnConstraints = concatMap mpnConstraints ps+ , mpnFuns = Map.unions (map mpnFuns ps)+ , mpnTySyn = Map.unions (map mpnTySyn ps)+ , mpnDoc = Nothing+ }+ where+ ps = map mpParameters (Map.elems mps)+++-- | A module parameter. Corresponds to a "signature import".+-- A single module parameter can bring multiple things in scope.+data ModParam = ModParam+ { mpName :: Ident+ -- ^ The name of a functor parameter.++ , mpQual :: !(Maybe ModName)+ -- ^ This is the qualifier for the parameter. We use it to+ -- derive parameter names when doing `_` imports.++ , mpIface :: ImpName Name+ -- ^ The interface corresponding to this parameter.+ -- This is thing in `import interface`++ , mpParameters :: ModParamNames+ {- ^ These are the actual parameters, not the ones in the interface+ For example if the same interface is used for multiple parameters+ the `ifmpParameters` would all be different. -}+ } deriving (Show, Generic, NFData)++-- | Information about the names brought in through an "interface import".+-- This is also used to keep information about.+data ModParamNames = ModParamNames+ { mpnTypes :: Map Name ModTParam+ -- ^ Type parameters++ , mpnTySyn :: !(Map Name TySyn)+ -- ^ Type synonyms++ , mpnConstraints :: [Located Prop]+ -- ^ Constraints on param. types+++ , mpnFuns :: Map.Map Name ModVParam+ -- ^ Value parameters++ , mpnDoc :: !(Maybe Text)+ -- ^ Documentation about the interface.+ } deriving (Show, Generic, NFData)+ -- | A type parameter of a module. data ModTParam = ModTParam { mtpName :: Name , mtpKind :: Kind- , mtpNumber :: !Int -- ^ The number of the parameter in the module- -- This is used when we move parameters from the module- -- level to individual declarations- -- (type synonyms in particular) , mtpDoc :: Maybe Text } deriving (Show,Generic,NFData) +-- | This is how module parameters appear in actual types. mtpParam :: ModTParam -> TParam mtpParam mtp = TParam { tpUnique = nameUnique (mtpName mtp) , tpKind = mtpKind mtp@@ -64,9 +124,9 @@ { mvpName :: Name , mvpType :: Schema , mvpDoc :: Maybe Text- , mvpFixity :: Maybe Fixity+ , mvpFixity :: Maybe Fixity -- XXX: This should be in the name? } deriving (Show,Generic,NFData)-+-------------------------------------------------------------------------------- @@ -259,6 +319,7 @@ data Newtype = Newtype { ntName :: Name , ntParams :: [TParam] , ntConstraints :: [Prop]+ , ntConName :: !Name , ntFields :: RecordMap Ident Type , ntDoc :: Maybe Text } deriving (Show, Generic, NFData)@@ -285,6 +346,8 @@ -------------------------------------------------------------------------------- +instance HasKind AbstractType where+ kindOf at = foldr (:->) (atKind at) (map kindOf (fst (atCtrs at))) instance HasKind TVar where kindOf (TVFree _ k _ _) = k@@ -696,7 +759,7 @@ tFun a b = TCon (TC TCFun) [a,b] -- | Eliminate outermost type synonyms.-tNoUser :: Type -> Type+tNoUser :: Type -> Type tNoUser t = case t of TUser _ _ a -> tNoUser a _ -> t@@ -847,7 +910,50 @@ where prop = TCon (PC PPrime) [ty] +-- Negation -------------------------------------------------------------------- +{-| `pNegNumeric` negates a simple (i.e., not And, not prime, etc) prop+over numeric type vars. The result is a conjunction of properties. -}+pNegNumeric :: Prop -> [Prop]+pNegNumeric prop =+ case tNoUser prop of+ TCon tcon tys ->+ case tcon of+ PC pc ->+ case pc of++ -- not (x == y) <=> x /= y+ PEqual -> [TCon (PC PNeq) tys]++ -- not (x /= y) <=> x == y+ PNeq -> [TCon (PC PEqual) tys]++ -- not (x >= y) <=> x /= y and y >= x+ PGeq -> [TCon (PC PNeq) tys, TCon (PC PGeq) (reverse tys)]++ -- not (fin x) <=> x == Inf+ PFin | [ty] <- tys -> [ty =#= tInf]+ | otherwise -> bad++ -- not True <=> 0 == 1+ PTrue -> [TCon (PC PEqual) [tZero, tOne]]++ _ -> bad++ TError _ki -> [prop] -- propogates `TError`++ TC _tc -> bad+ TF _tf -> bad++ _ -> bad++ where+ bad = panic "pNegNumeric"+ [ "Unexpeceted numeric constraint:"+ , pretty prop+ ]++ -------------------------------------------------------------------------------- noFreeVariables :: FVS t => t -> Bool@@ -873,6 +979,34 @@ TRec fs -> fvs (recordElements fs) TNewtype _nt ts -> fvs ts ++-- | Find the abstract types mentioned in a type.+class FreeAbstract t where+ freeAbstract :: t -> Set UserTC++instance FreeAbstract a => FreeAbstract [a] where+ freeAbstract = Set.unions . map freeAbstract++instance (FreeAbstract a, FreeAbstract b) => FreeAbstract (a,b) where+ freeAbstract (a,b) = Set.union (freeAbstract a) (freeAbstract b)++instance FreeAbstract TCon where+ freeAbstract tc =+ case tc of+ TC (TCAbstract ut) -> Set.singleton ut+ _ -> Set.empty++instance FreeAbstract Type where+ freeAbstract ty =+ case ty of+ TCon tc ts -> freeAbstract (tc,ts)+ TVar {} -> Set.empty+ TUser _ _ t -> freeAbstract t+ TRec fs -> freeAbstract (recordElements fs)+ TNewtype _nt ts -> freeAbstract ts+++ instance FVS a => FVS (Maybe a) where fvs Nothing = Set.empty fvs (Just x) = fvs x@@ -888,10 +1022,6 @@ Set.difference (Set.union (fvs ps) (fvs t)) bound where bound = Set.fromList (map tpVar as) ---- -- Pretty Printing ------------------------------------------------------------- instance PP TParam where@@ -924,7 +1054,18 @@ ps = ntParams nt nm = addTNames ps emptyNameMap +ppNewtypeFull :: Newtype -> Doc+ppNewtypeFull nt =+ text "newtype" <+> pp (ntName nt) <+> hsep (map (ppWithNamesPrec nm 9) ps)+ $$ nest 2 (cs $$ ("=" <+> pp (ntConName nt) $$ nest 2 fs))+ where+ ps = ntParams nt+ nm = addTNames ps emptyNameMap+ fs = vcat [ pp f <.> ":" <+> pp t | (f,t) <- canonicalFields (ntFields nt) ]+ cs = vcat (map pp (ntConstraints nt)) ++ instance PP Schema where ppPrec = ppWithNamesPrec IntMap.empty @@ -1115,7 +1256,8 @@ TypeParamInstPos f n -> mk (sh f ++ "_" ++ show n) DefinitionOf x -> case nameInfo x of- Declared m SystemName | m == TopModule exprModName -> mk "it"+ GlobalName SystemName og+ | ogModule og == TopModule exprModName -> mk "it" _ -> using x LenOfCompGen -> mk "n" GeneratorOfListComp -> "seq"@@ -1176,3 +1318,24 @@ GeneratorOfListComp -> "generator in a list comprehension" FunApp -> "function call" TypeErrorPlaceHolder -> "type error place-holder"++instance PP ModParamNames where+ ppPrec _ ps =+ let tps = Map.elems (mpnTypes ps)+ in+ vcat $ map pp tps +++ if null (mpnConstraints ps) then [] else+ [ "type constraint" <+>+ parens (commaSep (map (pp . thing) (mpnConstraints ps)))+ ] +++ [ pp t | t <- Map.elems (mpnTySyn ps) ] +++ map pp (Map.elems (mpnFuns ps))++instance PP ModTParam where+ ppPrec _ p =+ "type" <+> pp (mtpName p) <+> ":" <+> pp (mtpKind p)++instance PP ModVParam where+ ppPrec _ p = pp (mvpName p) <+> ":" <+> pp (mvpType p)++
src/Cryptol/TypeCheck/TypeOf.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE Safe #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE PatternGuards #-}+{-# LANGUAGE NamedFieldPuns #-} module Cryptol.TypeCheck.TypeOf ( fastTypeOf , fastSchemaOf@@ -43,6 +44,7 @@ Just (_, t) -> t Nothing -> panic "Cryptol.TypeCheck.TypeOf.fastTypeOf" [ "EApp with non-function operator" ]+ EPropGuards _guards sType -> sType -- Polymorphic fragment EVar {} -> polymorphic ETAbs {} -> polymorphic@@ -111,8 +113,11 @@ EComp {} -> monomorphic EApp {} -> monomorphic EAbs {} -> monomorphic++ -- PropGuards+ EPropGuards _ t -> Forall {sVars = [], sProps = [], sType = t} where- monomorphic = Forall [] [] (fastTypeOf tyenv expr)+ monomorphic = Forall {sVars = [], sProps = [], sType = fastTypeOf tyenv expr} -- | Apply a substitution to a type *without* simplifying -- constraints like @Arith [n]a@ to @Arith a@. (This is in contrast to
src/Cryptol/TypeCheck/TypePat.hs view
@@ -1,5 +1,6 @@ -- See Note [-Wincomplete-uni-patterns and irrefutable patterns] {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}+{-# LANGUAGE Safe #-} module Cryptol.TypeCheck.TypePat ( aInf, aNat, aNat' @@ -15,6 +16,7 @@ , aTVar , aFreeTVar+ , anAbstractType , aBit , aSeq , aWord@@ -123,6 +125,11 @@ aTVar = \a -> case tNoUser a of TVar x -> return x _ -> mzero++anAbstractType :: Pat Type UserTC+anAbstractType = \a -> case tNoUser a of+ TCon (TC (TCAbstract ut)) [] -> pure ut+ _ -> mzero aFreeTVar :: Pat Type TVar aFreeTVar t =
+ src/Cryptol/Utils/Benchmark.hs view
@@ -0,0 +1,36 @@+-- | Simple benchmarking of IO functions.+module Cryptol.Utils.Benchmark+ ( BenchmarkStats (..)+ , benchmark+ , secs+ ) where++import Criterion.Measurement (runBenchmark, secs, threshold)+import Criterion.Measurement.Types+import Data.Int+import qualified Data.Vector as V+import qualified Data.Vector.Unboxed as U++-- | Statistics returned by 'benchmark'.+--+-- This is extremely crude compared to the full analysis that criterion can do,+-- but is enough for now.+data BenchmarkStats = BenchmarkStats+ { benchAvgTime :: !Double+ , benchAvgCpuTime :: !Double+ , benchAvgCycles :: !Int64+ } deriving Show++-- | Benchmark the application of the given function to the given input and the+-- execution of the resulting IO action to WHNF, spending at least the given+-- amount of time in seconds to collect measurements.+benchmark :: Double -> (a -> IO b) -> a -> IO BenchmarkStats+benchmark period f x = do+ (meas, _) <- runBenchmark (whnfAppIO f x) period+ let meas' = rescale <$> V.filter ((>= threshold) . measTime) meas+ len = length meas'+ sumMeasure sel = U.sum $ measure sel meas'+ pure BenchmarkStats+ { benchAvgTime = sumMeasure measTime / fromIntegral len+ , benchAvgCpuTime = sumMeasure measCpuTime / fromIntegral len+ , benchAvgCycles = sumMeasure measCycles `div` fromIntegral len }
src/Cryptol/Utils/Fixity.hs view
@@ -23,10 +23,10 @@ -- | Information about associativity. data Assoc = LeftAssoc | RightAssoc | NonAssoc- deriving (Show, Eq, Generic, NFData)+ deriving (Show, Eq, Ord, Generic, NFData) data Fixity = Fixity { fAssoc :: !Assoc, fLevel :: !Int }- deriving (Eq, Generic, NFData, Show)+ deriving (Eq, Ord, Generic, NFData, Show) data FixityCmp = FCError | FCLeft
src/Cryptol/Utils/Ident.hs view
@@ -6,24 +6,29 @@ -- Stability : provisional -- Portability : portable -{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE OverloadedStrings #-} module Cryptol.Utils.Ident ( -- * Module names ModPath(..) , apPathRoot , modPathCommon+ , modPathIsOrContains , topModuleFor , modPathSplit+ , modPathIsNormal , ModName , modNameToText , textToModName , modNameChunks+ , modNameChunksText , packModName , preludeName , preludeReferenceName+ , undefinedModName , floatName , suiteBName , arrayName@@ -31,10 +36,10 @@ , interactiveName , noModuleName , exprModName-- , isParamInstModName- , paramInstModName- , notParamInstModName+ , modNameArg+ , modNameIfaceMod+ , modNameToNormalModName+ , modNameIsNormal -- * Identifiers , Ident@@ -47,6 +52,9 @@ , nullIdent , identText , modParamIdent+ , identAnonArg+ , identAnonIfaceMod+ , identIsNormal -- * Namespaces , Namespace(..)@@ -54,6 +62,8 @@ -- * Original names , OrigName(..)+ , OrigSource(..)+ , ogFromModParam -- * Identifiers for primitives , PrimIdent(..)@@ -67,11 +77,14 @@ import Control.DeepSeq (NFData) import Data.Char (isSpace) import Data.List (unfoldr)+import Data.Text (Text) import qualified Data.Text as T import Data.String (IsString(..)) import GHC.Generics (Generic) +import Cryptol.Utils.Panic(panic) + -------------------------------------------------------------------------------- -- | Namespaces for names@@ -115,6 +128,14 @@ (x:xs',y:ys') | x == y -> findCommon (Nested com x) xs' ys' _ -> (com, xs, ys) +-- | Does the first module path contain the second?+-- This returns true if the paths are the same.+modPathIsOrContains :: ModPath -> ModPath -> Bool+modPathIsOrContains p1 p2 =+ case modPathCommon p1 p2 of+ Just (_,[],_) -> True+ _ -> False+ modPathSplit :: ModPath -> (ModName, [Ident]) modPathSplit p0 = (top,reverse xs) where@@ -125,47 +146,67 @@ Nested b i -> (a, i:bs) where (a,bs) = go b -+modPathIsNormal :: ModPath -> Bool+modPathIsNormal p = modNameIsNormal m && all identIsNormal is+ where (m,is) = modPathSplit p -------------------------------------------------------------------------------- -- | Top-level Module names are just text.-data ModName = ModName T.Text+data ModName = ModName Text MaybeAnon deriving (Eq,Ord,Show,Generic) instance NFData ModName -modNameToText :: ModName -> T.Text-modNameToText (ModName x) = x+-- | Change a normal module name to a module name to be used for an+-- anonnymous argument.+modNameArg :: ModName -> ModName+modNameArg (ModName m fl) =+ case fl of+ NormalName -> ModName m AnonModArgName+ AnonModArgName -> panic "modNameArg" ["Name is not normal"]+ AnonIfaceModName -> panic "modNameArg" ["Name is not normal"] -textToModName :: T.Text -> ModName-textToModName = ModName+-- | Change a normal module name to a module name to be used for an+-- anonnymous interface.+modNameIfaceMod :: ModName -> ModName+modNameIfaceMod (ModName m fl) =+ case fl of+ NormalName -> ModName m AnonIfaceModName+ AnonModArgName -> panic "modNameIfaceMod" ["Name is not normal"]+ AnonIfaceModName -> panic "modNameIfaceMod" ["Name is not normal"] -modNameChunks :: ModName -> [String]-modNameChunks = unfoldr step . modNameToText . notParamInstModName- where- step str- | T.null str = Nothing- | otherwise = case T.breakOn modSep str of- (a,b) -> Just (T.unpack a,T.drop (T.length modSep) b)+-- | This is used when we check that the name of a module matches the+-- file where it is defined.+modNameToNormalModName :: ModName -> ModName+modNameToNormalModName (ModName t _) = ModName t NormalName -isParamInstModName :: ModName -> Bool-isParamInstModName (ModName x) = modInstPref `T.isPrefixOf` x+modNameToText :: ModName -> Text+modNameToText (ModName x fl) = maybeAnonText fl x --- | Convert a parameterized module's name to the name of the module--- containing the same definitions but with explicit parameters on each--- definition.-paramInstModName :: ModName -> ModName-paramInstModName (ModName x)- | modInstPref `T.isPrefixOf` x = ModName x- | otherwise = ModName (T.append modInstPref x)+-- | This is useful when we want to hide anonymous modules.+modNameIsNormal :: ModName -> Bool+modNameIsNormal (ModName _ fl) = isNormal fl +-- | Make a normal module name out of text.+textToModName :: T.Text -> ModName+textToModName txt = ModName txt NormalName -notParamInstModName :: ModName -> ModName-notParamInstModName (ModName x)- | modInstPref `T.isPrefixOf` x = ModName (T.drop (T.length modInstPref) x)- | otherwise = ModName x+-- | Break up a module name on the separators, `Text` version.+modNameChunksText :: ModName -> [T.Text]+modNameChunksText (ModName x fl) = unfoldr step x+ where+ step str+ | T.null str = Nothing+ | otherwise =+ case T.breakOn modSep str of+ (a,b)+ | T.null b -> Just (maybeAnonText fl str, b)+ | otherwise -> Just (a,T.drop (T.length modSep) b) +-- | Break up a module name on the separators, `String` version+modNameChunks :: ModName -> [String]+modNameChunks = map T.unpack . modNameChunksText packModName :: [T.Text] -> ModName packModName strs = textToModName (T.intercalate modSep (map trim strs))@@ -176,13 +217,12 @@ modSep :: T.Text modSep = "::" -modInstPref :: T.Text-modInstPref = "`"-- preludeName :: ModName preludeName = packModName ["Cryptol"] +undefinedModName :: ModName+undefinedModName = packModName ["Undefined module"]+ preludeReferenceName :: ModName preludeReferenceName = packModName ["Cryptol","Reference"] @@ -213,16 +253,32 @@ data OrigName = OrigName { ogNamespace :: Namespace , ogModule :: ModPath+ , ogSource :: OrigSource , ogName :: Ident } deriving (Eq,Ord,Show,Generic,NFData) +-- | Describes where a top-level name came from+data OrigSource =+ FromDefinition+ | FromFunctorInst+ | FromModParam Ident+ deriving (Eq,Ord,Show,Generic,NFData) +-- | Returns true iff the 'ogSource' of the given 'OrigName' is 'FromModParam'+ogFromModParam :: OrigName -> Bool+ogFromModParam og = case ogSource og of+ FromModParam _ -> True+ _ -> False++ -------------------------------------------------------------------------------- --- | Identifiers, along with a flag that indicates whether or not they're infix--- operators. The boolean is present just as cached information from the lexer,--- and never used during comparisons.-data Ident = Ident Bool T.Text+{- | The type of identifiers.+ * The boolean flag indicates whether or not they're infix operators.+ The boolean is present just as cached information from the lexer,+ and never used during comparisons.+ * The MaybeAnon indicates if this is an anonymous name -}+data Ident = Ident Bool MaybeAnon T.Text deriving (Show,Generic) instance Eq Ident where@@ -230,39 +286,82 @@ a /= b = compare a b /= EQ instance Ord Ident where- compare (Ident _ i1) (Ident _ i2) = compare i1 i2+ compare (Ident _ mb1 i1) (Ident _ mb2 i2) = compare (mb1,i1) (mb2,i2) instance IsString Ident where fromString str = mkIdent (T.pack str) instance NFData Ident +-- | Make a normal (i.e., not anonymous) identifier packIdent :: String -> Ident packIdent = mkIdent . T.pack +-- | Make a normal (i.e., not anonymous) identifier packInfix :: String -> Ident packInfix = mkInfix . T.pack unpackIdent :: Ident -> String unpackIdent = T.unpack . identText +-- | Make a normal (i.e., not anonymous) identifier mkIdent :: T.Text -> Ident-mkIdent = Ident False+mkIdent = Ident False NormalName mkInfix :: T.Text -> Ident-mkInfix = Ident True+mkInfix = Ident True NormalName isInfixIdent :: Ident -> Bool-isInfixIdent (Ident b _) = b+isInfixIdent (Ident b _ _) = b nullIdent :: Ident -> Bool-nullIdent (Ident _ t) = T.null t+nullIdent = T.null . identText identText :: Ident -> T.Text-identText (Ident _ t) = t+identText (Ident _ mb t) = maybeAnonText mb t modParamIdent :: Ident -> Ident-modParamIdent (Ident x t) = Ident x (T.append (T.pack "module parameter ") t)+modParamIdent (Ident x a t) =+ Ident x a (T.append (T.pack "module parameter ") t)++-- | Make an anonymous identifier for the module corresponding to+-- a `where` block in a functor instantiation.+identAnonArg :: Ident -> Ident+identAnonArg (Ident b _ txt) = Ident b AnonModArgName txt++-- | Make an anonymous identifier for the interface corresponding to+-- a `parameter` declaration.+identAnonIfaceMod :: Ident -> Ident+identAnonIfaceMod (Ident b _ txt) = Ident b AnonIfaceModName txt++identIsNormal :: Ident -> Bool+identIsNormal (Ident _ mb _) = isNormal mb++--------------------------------------------------------------------------------++-- | Information about anonymous names.+data MaybeAnon = NormalName -- ^ Not an anonymous name.+ | AnonModArgName -- ^ Anonymous module (from `where`)+ | AnonIfaceModName -- ^ Anonymous interface (from `parameter`)+ deriving (Eq,Ord,Show,Generic)++instance NFData MaybeAnon++-- | Modify a name, if it is a nonymous+maybeAnonText :: MaybeAnon -> Text -> Text+maybeAnonText mb txt =+ case mb of+ NormalName -> txt+ AnonModArgName -> "`where` argument of " <> txt+ AnonIfaceModName -> "`parameter` interface of " <> txt++isNormal :: MaybeAnon -> Bool+isNormal mb =+ case mb of+ NormalName -> True+ _ -> False++ --------------------------------------------------------------------------------
src/Cryptol/Utils/PP.hs view
@@ -7,7 +7,7 @@ -- Portability : portable {-# LANGUAGE Safe #-}-+{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}@@ -23,6 +23,7 @@ import Data.Void (Void) import GHC.Generics (Generic) import qualified Prettyprinter as PP+import qualified Prettyprinter.Util as PP import qualified Prettyprinter.Render.String as PP -- | How to pretty print things when evaluating@@ -49,7 +50,8 @@ | AutoExponent -- ^ Only show exponent when needed deriving Show -data FieldOrder = DisplayOrder | CanonicalOrder deriving (Bounded, Enum, Eq, Ord, Read, Show)+data FieldOrder = DisplayOrder | CanonicalOrder+ deriving (Bounded, Enum, Eq, Ord, Read, Show) defaultPPOpts :: PPOpts@@ -91,7 +93,9 @@ -- | Never qualify names from this module. neverQualifyMod :: ModPath -> NameDisp neverQualifyMod mn = NameDisp $ \n ->- if ogModule n == mn then Just UnQualified else Nothing+ case ogSource n of+ FromDefinition | ogModule n == mn -> Just UnQualified+ _ -> Nothing neverQualify :: NameDisp neverQualify = NameDisp $ \ _ -> Just UnQualified@@ -102,25 +106,52 @@ extend :: NameDisp -> NameDisp -> NameDisp extend = mappend --- | Get the format for a name. When 'Nothing' is returned, the name is not--- currently in scope.+-- | Get the format for a name. getNameFormat :: OrigName -> NameDisp -> NameFormat getNameFormat m (NameDisp f) = fromMaybe NotInScope (f m) getNameFormat _ EmptyNameDisp = NotInScope -- | Produce a document in the context of the current 'NameDisp'. withNameDisp :: (NameDisp -> Doc) -> Doc-withNameDisp k = Doc (\disp -> runDoc disp (k disp))+withNameDisp k = withPPCfg (k . ppcfgNameDisp) +-- | Produce a document in the context of the current configuration.+withPPCfg :: (PPCfg -> Doc) -> Doc+withPPCfg k = Doc (\cfg -> runDocWith cfg (k cfg))+ -- | Fix the way that names are displayed inside of a doc. fixNameDisp :: NameDisp -> Doc -> Doc-fixNameDisp disp (Doc f) = Doc (\ _ -> f disp)+fixNameDisp disp d =+ withPPCfg (\cfg -> fixPPCfg cfg { ppcfgNameDisp = disp } d) +-- | Fix the way that names are displayed inside of a doc.+fixPPCfg :: PPCfg -> Doc -> Doc+fixPPCfg cfg (Doc f) = Doc (\_ -> f cfg) +updPPCfg :: (PPCfg -> PPCfg) -> Doc -> Doc+updPPCfg f d = withPPCfg (\cfg -> fixPPCfg (f cfg) d)++debugShowUniques :: Doc -> Doc+debugShowUniques = updPPCfg \cfg -> cfg { ppcfgShowNameUniques = True }++++ -- Documents ------------------------------------------------------------------- -newtype Doc = Doc (NameDisp -> PP.Doc Void) deriving (Generic, NFData)+data PPCfg = PPCfg+ { ppcfgNameDisp :: NameDisp+ , ppcfgShowNameUniques :: Bool+ } +defaultPPCfg :: PPCfg+defaultPPCfg = PPCfg+ { ppcfgNameDisp = mempty+ , ppcfgShowNameUniques = False+ }++newtype Doc = Doc (PPCfg -> PP.Doc Void) deriving (Generic, NFData)+ instance Semigroup Doc where (<>) = liftPP2 (<>) @@ -128,18 +159,22 @@ mempty = liftPP mempty mappend = (<>) +runDocWith :: PPCfg -> Doc -> PP.Doc Void+runDocWith names (Doc f) = f names+ runDoc :: NameDisp -> Doc -> PP.Doc Void-runDoc names (Doc f) = f names+runDoc disp = runDocWith defaultPPCfg { ppcfgNameDisp = disp } instance Show Doc where- show d = PP.renderString (PP.layoutPretty opts (runDoc mempty d))- where opts = PP.defaultLayoutOptions{ PP.layoutPageWidth = PP.AvailablePerLine 100 0.666 }+ show d = PP.renderString (PP.layoutPretty opts (runDocWith defaultPPCfg d))+ where opts = PP.defaultLayoutOptions+ { PP.layoutPageWidth = PP.AvailablePerLine 100 0.666 } instance IsString Doc where fromString = text renderOneLine :: Doc -> String-renderOneLine d = PP.renderString (PP.layoutCompact (runDoc mempty d))+renderOneLine d = PP.renderString (PP.layoutCompact (runDocWith defaultPPCfg d)) class PP a where ppPrec :: Int -> a -> Doc@@ -231,6 +266,9 @@ liftSep :: ([PP.Doc Void] -> PP.Doc Void) -> ([Doc] -> Doc) liftSep f ds = Doc (\e -> f [ d e | Doc d <- ds ]) +reflow :: T.Text -> Doc+reflow x = liftPP (PP.reflow x)+ infixl 6 <.>, <+>, </> (<.>) :: Doc -> Doc -> Doc@@ -337,6 +375,10 @@ colon :: Doc colon = liftPP PP.colon +pipe :: Doc+pipe = liftPP PP.pipe++ instance PP T.Text where ppPrec _ str = text (T.unpack str) @@ -346,7 +388,6 @@ instance PP ModName where ppPrec _ = text . T.unpack . modNameToText - instance PP Assoc where ppPrec _ LeftAssoc = text "left-associative" ppPrec _ RightAssoc = text "right-associative"@@ -368,7 +409,10 @@ case getNameFormat og disp of UnQualified -> pp (ogName og) Qualified m -> ppQual (TopModule m) (pp (ogName og))- NotInScope -> ppQual (ogModule og) (pp (ogName og))+ NotInScope -> ppQual (ogModule og)+ case ogSource og of+ FromModParam x -> pp x <.> "::" <.> pp (ogName og)+ _ -> pp (ogName og) where ppQual mo x = case mo of@@ -380,6 +424,9 @@ instance PP Namespace where ppPrec _ ns = case ns of- NSValue -> "/*value*/"- NSType -> "/*type*/"- NSModule -> "/*module*/"+ NSValue -> "/*value*/"+ NSType -> "/*type*/"+ NSModule -> "/*module*/"++instance PP PrimIdent where+ ppPrec _ (PrimIdent m t) = pp m <.> text (T.unpack t)
src/Cryptol/Utils/Panic.hs view
@@ -8,7 +8,7 @@ {-# LANGUAGE Trustworthy, TemplateHaskell #-} module Cryptol.Utils.Panic- (HasCallStack, CryptolPanic, Cryptol, Panic, panic) where+ (HasCallStack, CryptolPanic, Cryptol, Panic, panic, xxxTODO) where import Panic hiding (panic) import qualified Panic as Panic@@ -19,6 +19,9 @@ panic :: HasCallStack => String -> [String] -> a panic = Panic.panic Cryptol++xxxTODO :: HasCallStack => String -> a+xxxTODO x = panic "TODO" [x] instance PanicComponent Cryptol where panicComponentName _ = "Cryptol"
src/Cryptol/Utils/Patterns.hs view
@@ -2,6 +2,7 @@ {-# Language FunctionalDependencies #-} {-# Language FlexibleInstances #-} {-# Language TypeFamilies, UndecidableInstances #-}+{-# Language TypeOperators #-} module Cryptol.Utils.Patterns where import Control.Monad(liftM,liftM2,ap,MonadPlus(..),guard)
src/Cryptol/Utils/RecordMap.hs view
@@ -14,6 +14,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE Safe #-} module Cryptol.Utils.RecordMap ( RecordMap@@ -21,6 +22,7 @@ , canonicalFields , displayFields , recordElements+ , displayElements , fieldSet , recordFromFields , recordFromFieldsErr@@ -88,6 +90,11 @@ -- | Return a list of field/value pairs in canonical order. canonicalFields :: RecordMap a b -> [(a,b)] canonicalFields = Map.toList . recordMap++-- | Retrieve the elements of the record in display order+-- of the field names.+displayElements :: (Show a, Ord a) => RecordMap a b -> [b]+displayElements = map snd . displayFields -- | Return a list of field/value pairs in display order. displayFields :: (Show a, Ord a) => RecordMap a b -> [(a,b)]
+ src/Cryptol/Utils/Types.hs view
@@ -0,0 +1,10 @@+-- | Useful information about various types.+module Cryptol.Utils.Types where++-- | Exponent and precision of 32-bit IEEE-754 floating point.+float32ExpPrec :: (Integer, Integer)+float32ExpPrec = (8, 24)++-- | Exponent and precision of 64-bit IEEE-754 floating point.+float64ExpPrec :: (Integer, Integer)+float64ExpPrec = (11, 53)
src/Cryptol/Version.hs view
@@ -6,7 +6,7 @@ -- Stability : provisional -- Portability : portable -{-# LANGUAGE Safe #-}+{-# LANGUAGE CPP #-} module Cryptol.Version ( commitHash@@ -39,6 +39,9 @@ putLn ("Cryptol " ++ ver) putLn ("Git commit " ++ commitHash) putLn (" branch " ++ commitBranch ++ dirtyLab)+#ifdef FFI_ENABLED+ putLn "FFI enabled"+#endif where dirtyLab | commitDirty = " (non-committed files present during build)" | otherwise = ""