cryptol 2.11.0 → 2.12.0
raw patch · 79 files changed
+6573/−4328 lines, 79 filesdep +prettyprinterdep −prettydep −randomdep ~sbvdep ~simple-smtdep ~what4PVP ok
version bump matches the API change (PVP)
Dependencies added: prettyprinter
Dependencies removed: pretty, random
Dependency ranges changed: sbv, simple-smt, what4
API changes (from Hackage documentation)
- Cryptol.Backend.Monad: type CallStack = Seq (Name, Range)
- Cryptol.Eval.Generic: barrelShifter :: Backend sym => sym -> (SeqMap sym -> Integer -> SEval sym (SeqMap sym)) -> SeqMap sym -> [SBit sym] -> SEval sym (SeqMap sym)
- Cryptol.Eval.Generic: bitsValueLessThan :: Backend sym => sym -> Integer -> [SBit sym] -> Integer -> SEval sym (SBit sym)
- Cryptol.Eval.Generic: ecSplitV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: enumerateIntBits :: Backend sym => sym -> Nat' -> TValue -> SInteger sym -> SEval sym [SBit sym]
- Cryptol.Eval.Generic: enumerateIntBits' :: Backend sym => sym -> Integer -> SInteger sym -> SEval sym [SBit sym]
- Cryptol.Eval.Generic: extractWordVal :: Backend sym => sym -> Integer -> Integer -> WordValue sym -> SEval sym (WordValue sym)
- Cryptol.Eval.Generic: iteValue :: Backend sym => sym -> SBit sym -> SEval sym (GenValue sym) -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: joinWordVal :: Backend sym => sym -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)
- Cryptol.Eval.Generic: joinWords :: forall sym. Backend sym => sym -> Integer -> Integer -> SeqMap sym -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: mergeSeqMap :: Backend sym => sym -> SBit sym -> SeqMap sym -> SeqMap sym -> SeqMap sym
- Cryptol.Eval.Generic: mergeValue :: Backend sym => sym -> SBit sym -> GenValue sym -> GenValue sym -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: mergeValue' :: Backend sym => sym -> SBit sym -> SEval sym (GenValue sym) -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: mergeWord :: Backend sym => sym -> SBit sym -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)
- Cryptol.Eval.Generic: mergeWord' :: Backend sym => sym -> SBit sym -> SEval sym (WordValue sym) -> SEval sym (WordValue sym) -> SEval sym (WordValue sym)
- Cryptol.Eval.Generic: splitAtV :: Backend sym => sym -> Nat' -> Nat' -> TValue -> GenValue sym -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: splitWordVal :: Backend sym => sym -> Integer -> Integer -> WordValue sym -> SEval sym (WordValue sym, WordValue sym)
- Cryptol.Eval.Generic: wordValLogicOp :: Backend sym => sym -> (SBit sym -> SBit sym -> SEval sym (SBit sym)) -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)
- Cryptol.Eval.Generic: wordValUnaryOp :: Backend sym => sym -> (SBit sym -> SEval sym (SBit sym)) -> (SWord sym -> SEval sym (SWord sym)) -> WordValue sym -> SEval sym (WordValue sym)
- Cryptol.Eval.Value: IndexSeqMap :: !Integer -> SEval sym (GenValue sym) -> SeqMap sym
- Cryptol.Eval.Value: LargeBitsVal :: !Integer -> !SeqMap sym -> WordValue sym
- Cryptol.Eval.Value: UpdateSeqMap :: !Map Integer (SEval sym (GenValue sym)) -> !Integer -> SEval sym (GenValue sym) -> SeqMap sym
- Cryptol.Eval.Value: WordVal :: !SWord sym -> WordValue sym
- Cryptol.Eval.Value: asBitsMap :: Backend sym => sym -> WordValue sym -> SeqMap sym
- Cryptol.Eval.Value: asWordVal :: Backend sym => sym -> WordValue sym -> SEval sym (SWord sym)
- Cryptol.Eval.Value: concatSeqMap :: Integer -> SeqMap sym -> SeqMap sym -> SeqMap sym
- Cryptol.Eval.Value: data SeqMap sym
- Cryptol.Eval.Value: data WordValue sym
- Cryptol.Eval.Value: dropSeqMap :: Integer -> SeqMap sym -> SeqMap sym
- Cryptol.Eval.Value: enumerateSeqMap :: Integral n => n -> SeqMap sym -> [SEval sym (GenValue sym)]
- Cryptol.Eval.Value: enumerateWordValue :: Backend sym => sym -> WordValue sym -> SEval sym [SBit sym]
- Cryptol.Eval.Value: enumerateWordValueRev :: Backend sym => sym -> WordValue sym -> SEval sym [SBit sym]
- Cryptol.Eval.Value: finiteSeqMap :: [SEval sym (GenValue sym)] -> SeqMap sym
- Cryptol.Eval.Value: forceWordValue :: Backend sym => WordValue sym -> SEval sym ()
- Cryptol.Eval.Value: indexWordValue :: Backend sym => sym -> WordValue sym -> Integer -> SEval sym (SBit sym)
- Cryptol.Eval.Value: infiniteSeqMap :: Backend sym => sym -> [SEval sym (GenValue sym)] -> SEval sym (SeqMap sym)
- Cryptol.Eval.Value: instance Cryptol.Backend.Backend sym => GHC.Show.Show (Cryptol.Eval.Value.GenValue sym)
- Cryptol.Eval.Value: instance GHC.Generics.Generic (Cryptol.Eval.Value.WordValue sym)
- Cryptol.Eval.Value: largeBitSize :: Integer
- Cryptol.Eval.Value: lookupSeqMap :: SeqMap sym -> Integer -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: mapSeqMap :: Backend sym => sym -> (GenValue sym -> SEval sym (GenValue sym)) -> SeqMap sym -> SEval sym (SeqMap sym)
- Cryptol.Eval.Value: memoMap :: Backend sym => sym -> SeqMap sym -> SEval sym (SeqMap sym)
- Cryptol.Eval.Value: reverseSeqMap :: Integer -> SeqMap sym -> SeqMap sym
- Cryptol.Eval.Value: splitSeqMap :: Integer -> SeqMap sym -> (SeqMap sym, SeqMap sym)
- Cryptol.Eval.Value: streamSeqMap :: SeqMap sym -> [SEval sym (GenValue sym)]
- Cryptol.Eval.Value: toFinSeq :: Backend sym => sym -> Integer -> TValue -> [GenValue sym] -> GenValue sym
- Cryptol.Eval.Value: toSeq :: Backend sym => sym -> Nat' -> TValue -> [GenValue sym] -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: toStream :: Backend sym => sym -> [GenValue sym] -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: updateSeqMap :: SeqMap sym -> Integer -> SEval sym (GenValue sym) -> SeqMap sym
- Cryptol.Eval.Value: updateWordValue :: Backend sym => sym -> WordValue sym -> Integer -> SEval sym (SBit sym) -> SEval sym (WordValue sym)
- Cryptol.Eval.Value: wordValueSize :: Backend sym => sym -> WordValue sym -> Integer
- Cryptol.Eval.Value: zipSeqMap :: Backend sym => sym -> (GenValue sym -> GenValue sym -> SEval sym (GenValue sym)) -> SeqMap sym -> SeqMap sym -> SEval sym (SeqMap sym)
- Cryptol.ModuleSystem: [meSolverConfig] :: ModuleEnv -> SolverConfig
- Cryptol.ModuleSystem: data Iface
- Cryptol.ModuleSystem.Base: importIface :: Import -> ModuleM (IfaceDecls, NamingEnv)
- Cryptol.ModuleSystem.Base: importIfaces :: [Import] -> ModuleM (IfaceDecls, NamingEnv)
- Cryptol.ModuleSystem.Env: NameIsDynamicDecl :: DeclProvenance
- Cryptol.ModuleSystem.Env: NameIsImportedFrom :: ModName -> DeclProvenance
- Cryptol.ModuleSystem.Env: NameIsLocalPrivate :: DeclProvenance
- Cryptol.ModuleSystem.Env: NameIsLocalPublic :: DeclProvenance
- Cryptol.ModuleSystem.Env: NameIsParameter :: DeclProvenance
- Cryptol.ModuleSystem.Env: [mctxTypeProvenace] :: ModContext -> Map Name DeclProvenance
- Cryptol.ModuleSystem.Env: [mctxValueProvenance] :: ModContext -> Map Name DeclProvenance
- Cryptol.ModuleSystem.Env: [meSolverConfig] :: ModuleEnv -> SolverConfig
- Cryptol.ModuleSystem.Env: data DeclProvenance
- Cryptol.ModuleSystem.Env: instance GHC.Classes.Eq Cryptol.ModuleSystem.Env.DeclProvenance
- Cryptol.ModuleSystem.Env: instance GHC.Classes.Ord Cryptol.ModuleSystem.Env.DeclProvenance
- Cryptol.ModuleSystem.Exports: [eBinds] :: ExportSpec name -> Set name
- Cryptol.ModuleSystem.Exports: [eTypes] :: ExportSpec name -> Set name
- Cryptol.ModuleSystem.Exports: data ExportSpec name
- Cryptol.ModuleSystem.Interface: data Iface
- Cryptol.ModuleSystem.Interface: genIface :: Module -> Iface
- Cryptol.ModuleSystem.Interface: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Interface.Iface
- Cryptol.ModuleSystem.Interface: instance GHC.Generics.Generic Cryptol.ModuleSystem.Interface.Iface
- Cryptol.ModuleSystem.Interface: instance GHC.Show.Show Cryptol.ModuleSystem.Interface.Iface
- Cryptol.ModuleSystem.Interface: mkIfaceDecl :: Decl -> IfaceDecl
- Cryptol.ModuleSystem.Monad: getSolverConfig :: ModuleM SolverConfig
- Cryptol.ModuleSystem.Monad: setSolver :: SolverConfig -> ModuleM ()
- Cryptol.ModuleSystem.Name: cmpNameLexical :: Name -> Name -> Ordering
- Cryptol.ModuleSystem.NamingEnv: [neExprs] :: NamingEnv -> !Map PName [Name]
- Cryptol.ModuleSystem.NamingEnv: [neTypes] :: NamingEnv -> !Map PName [Name]
- Cryptol.ModuleSystem.NamingEnv: data NamingEnv
- Cryptol.ModuleSystem.NamingEnv: interpImport :: Import -> IfaceDecls -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: namingEnv' :: BindsNames a => a -> Supply -> (NamingEnv, Supply)
- Cryptol.ModuleSystem.Renamer: ExpectedType :: Located PName -> NameDisp -> RenamerError
- Cryptol.ModuleSystem.Renamer: ExpectedValue :: Located PName -> NameDisp -> RenamerError
- Cryptol.ModuleSystem.Renamer: UnboundExpr :: Located PName -> NameDisp -> RenamerError
- Cryptol.ModuleSystem.Renamer: UnboundType :: Located PName -> NameDisp -> RenamerError
- Cryptol.ModuleSystem.Renamer: checkNamingEnv :: NamingEnv -> ([RenamerError], [RenamerWarning])
- Cryptol.ModuleSystem.Renamer: instance (GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (Cryptol.ModuleSystem.Renamer.RenameM a)
- Cryptol.ModuleSystem.Renamer: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Renamer.RenamerError
- Cryptol.ModuleSystem.Renamer: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Renamer.RenamerWarning
- Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Name.FreshM Cryptol.ModuleSystem.Renamer.RenameM
- Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.TopDecl
- Cryptol.ModuleSystem.Renamer: instance Cryptol.Utils.PP.PP Cryptol.ModuleSystem.Renamer.RenamerError
- Cryptol.ModuleSystem.Renamer: instance Cryptol.Utils.PP.PP Cryptol.ModuleSystem.Renamer.RenamerWarning
- Cryptol.ModuleSystem.Renamer: instance GHC.Base.Applicative Cryptol.ModuleSystem.Renamer.RenameM
- Cryptol.ModuleSystem.Renamer: instance GHC.Base.Functor Cryptol.ModuleSystem.Renamer.RenameM
- Cryptol.ModuleSystem.Renamer: instance GHC.Base.Monad Cryptol.ModuleSystem.Renamer.RenameM
- Cryptol.ModuleSystem.Renamer: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Cryptol.ModuleSystem.Renamer.RenameM a)
- Cryptol.ModuleSystem.Renamer: instance GHC.Classes.Eq Cryptol.ModuleSystem.Renamer.EnvCheck
- Cryptol.ModuleSystem.Renamer: instance GHC.Generics.Generic Cryptol.ModuleSystem.Renamer.RenamerError
- Cryptol.ModuleSystem.Renamer: instance GHC.Generics.Generic Cryptol.ModuleSystem.Renamer.RenamerWarning
- Cryptol.ModuleSystem.Renamer: instance GHC.Show.Show Cryptol.ModuleSystem.Renamer.EnvCheck
- Cryptol.ModuleSystem.Renamer: instance GHC.Show.Show Cryptol.ModuleSystem.Renamer.RenamerError
- Cryptol.ModuleSystem.Renamer: instance GHC.Show.Show Cryptol.ModuleSystem.Renamer.RenamerWarning
- Cryptol.ModuleSystem.Renamer: namingEnv' :: BindsNames a => a -> Supply -> (NamingEnv, Supply)
- Cryptol.Parser.AST: [mImports] :: Module name -> [Located Import]
- Cryptol.Parser.AST: data Import
- Cryptol.Parser.AST: data Module name
- Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.Module name)
- Cryptol.Parser.AST: instance Control.DeepSeq.NFData Cryptol.Parser.AST.Import
- Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.Module name)
- Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.Module name)
- Cryptol.Parser.AST: instance Cryptol.Parser.Position.HasLoc (Cryptol.Parser.AST.Module name)
- Cryptol.Parser.AST: instance Cryptol.Utils.PP.PP Cryptol.Parser.AST.Import
- Cryptol.Parser.AST: instance GHC.Classes.Eq Cryptol.Parser.AST.Import
- Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.Module name)
- Cryptol.Parser.AST: instance GHC.Generics.Generic Cryptol.Parser.AST.Import
- Cryptol.Parser.AST: instance GHC.Show.Show Cryptol.Parser.AST.Import
- Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.Module name)
- Cryptol.Parser.Names: allNamesD :: Ord name => Decl name -> [Located name]
- Cryptol.Parser.Names: boundLNames :: Ord name => [Located name] -> Set name -> Set name
- Cryptol.Parser.Names: namesArm :: Ord name => [Match name] -> ([Located name], Set name)
- Cryptol.Parser.Names: namesDef :: Ord name => BindDef name -> Set name
- Cryptol.Parser.Names: namesDs :: Ord name => [Decl name] -> ([Located name], Set name)
- Cryptol.Parser.Names: namesE :: Ord name => Expr name -> Set name
- Cryptol.Parser.Names: namesM :: Ord name => Match name -> ([Located name], Set name)
- Cryptol.Parser.Names: namesPs :: [Pattern name] -> [Located name]
- Cryptol.Parser.Names: namesUF :: Ord name => UpdField name -> Set name
- Cryptol.Parser.Names: tnamesB :: Ord name => Bind name -> Set name
- Cryptol.Parser.Names: tnamesDef :: Ord name => BindDef name -> Set name
- Cryptol.Parser.Names: tnamesDs :: Ord name => [Decl name] -> ([Located name], Set name)
- Cryptol.Parser.Names: tnamesE :: Ord name => Expr name -> Set name
- Cryptol.Parser.Names: tnamesM :: Ord name => Match name -> Set name
- Cryptol.Parser.Names: tnamesP :: Ord name => Pattern name -> Set name
- Cryptol.Parser.Names: tnamesS :: Ord name => Schema name -> Set name
- Cryptol.Parser.Names: tnamesTI :: Ord name => TypeInst name -> Set name
- Cryptol.Parser.Names: tnamesUF :: Ord name => UpdField name -> Set name
- Cryptol.Parser.NoPat: instance Cryptol.Parser.NoPat.RemovePatterns (Cryptol.Parser.AST.Module Cryptol.Parser.Name.PName)
- Cryptol.TypeCheck: [inpSolverConfig] :: InferInput -> SolverConfig
- Cryptol.TypeCheck.AST: ModTParam :: Name -> Kind -> !Int -> Maybe Text -> ModTParam
- Cryptol.TypeCheck.AST: ModVParam :: Name -> Schema -> Maybe Text -> Maybe Fixity -> ModVParam
- Cryptol.TypeCheck.AST: [eBinds] :: ExportSpec name -> Set name
- Cryptol.TypeCheck.AST: [eTypes] :: ExportSpec name -> Set name
- Cryptol.TypeCheck.AST: [mtpDoc] :: ModTParam -> Maybe Text
- Cryptol.TypeCheck.AST: [mtpKind] :: ModTParam -> Kind
- Cryptol.TypeCheck.AST: [mtpName] :: ModTParam -> Name
- Cryptol.TypeCheck.AST: [mtpNumber] :: ModTParam -> !Int
- Cryptol.TypeCheck.AST: [mvpDoc] :: ModVParam -> Maybe Text
- Cryptol.TypeCheck.AST: [mvpFixity] :: ModVParam -> Maybe Fixity
- Cryptol.TypeCheck.AST: [mvpName] :: ModVParam -> Name
- Cryptol.TypeCheck.AST: [mvpType] :: ModVParam -> Schema
- Cryptol.TypeCheck.AST: data ExportSpec name
- Cryptol.TypeCheck.AST: data Import
- Cryptol.TypeCheck.AST: data ModTParam
- Cryptol.TypeCheck.AST: data ModVParam
- Cryptol.TypeCheck.AST: data Module
- Cryptol.TypeCheck.AST: instance Control.DeepSeq.NFData Cryptol.TypeCheck.AST.ModTParam
- Cryptol.TypeCheck.AST: instance Control.DeepSeq.NFData Cryptol.TypeCheck.AST.ModVParam
- Cryptol.TypeCheck.AST: instance Control.DeepSeq.NFData Cryptol.TypeCheck.AST.Module
- Cryptol.TypeCheck.AST: instance Cryptol.Utils.PP.PP (Cryptol.TypeCheck.PP.WithNames Cryptol.TypeCheck.AST.Module)
- Cryptol.TypeCheck.AST: instance Cryptol.Utils.PP.PP Cryptol.TypeCheck.AST.Module
- Cryptol.TypeCheck.AST: instance GHC.Generics.Generic Cryptol.TypeCheck.AST.ModTParam
- Cryptol.TypeCheck.AST: instance GHC.Generics.Generic Cryptol.TypeCheck.AST.ModVParam
- Cryptol.TypeCheck.AST: instance GHC.Generics.Generic Cryptol.TypeCheck.AST.Module
- Cryptol.TypeCheck.AST: instance GHC.Show.Show Cryptol.TypeCheck.AST.ModTParam
- Cryptol.TypeCheck.AST: instance GHC.Show.Show Cryptol.TypeCheck.AST.ModVParam
- Cryptol.TypeCheck.AST: instance GHC.Show.Show Cryptol.TypeCheck.AST.Module
- Cryptol.TypeCheck.AST: mtpParam :: ModTParam -> TParam
- Cryptol.TypeCheck.Depends: AT :: ParameterType Name -> Maybe Text -> TyDecl
- Cryptol.TypeCheck.Depends: NT :: Newtype Name -> Maybe Text -> TyDecl
- Cryptol.TypeCheck.Depends: PS :: PropSyn Name -> Maybe Text -> TyDecl
- Cryptol.TypeCheck.Depends: PT :: PrimType Name -> Maybe Text -> TyDecl
- Cryptol.TypeCheck.Depends: TS :: TySyn Name -> Maybe Text -> TyDecl
- Cryptol.TypeCheck.Depends: class FromDecl d
- Cryptol.TypeCheck.Depends: combine :: [(Name, Located a)] -> InferM (Map Name (Located a))
- Cryptol.TypeCheck.Depends: combineMaps :: [Map Name (Located a)] -> InferM (Map Name (Located a))
- Cryptol.TypeCheck.Depends: data TyDecl
- Cryptol.TypeCheck.Depends: duplicates :: Ord a => [Located a] -> [(a, [Range])]
- Cryptol.TypeCheck.Depends: instance Cryptol.TypeCheck.Depends.FromDecl (Cryptol.Parser.AST.Decl Cryptol.ModuleSystem.Name.Name)
- Cryptol.TypeCheck.Depends: instance Cryptol.TypeCheck.Depends.FromDecl (Cryptol.Parser.AST.TopDecl Cryptol.ModuleSystem.Name.Name)
- Cryptol.TypeCheck.Depends: instance GHC.Show.Show Cryptol.TypeCheck.Depends.TyDecl
- Cryptol.TypeCheck.Depends: isTopDecl :: FromDecl d => d -> Bool
- Cryptol.TypeCheck.Depends: mkScc :: [(a, [Name], [Name])] -> [SCC a]
- Cryptol.TypeCheck.Depends: orderBinds :: [Bind Name] -> [SCC (Bind Name)]
- Cryptol.TypeCheck.Depends: orderTyDecls :: [TyDecl] -> InferM (Either Error [TyDecl])
- Cryptol.TypeCheck.Depends: setDocString :: Maybe Text -> TyDecl -> TyDecl
- Cryptol.TypeCheck.Depends: toBind :: FromDecl d => d -> Maybe (Bind Name)
- Cryptol.TypeCheck.Depends: toParamConstraints :: FromDecl d => d -> [Located (Prop Name)]
- Cryptol.TypeCheck.Depends: toParamFun :: FromDecl d => d -> Maybe (ParameterFun Name)
- Cryptol.TypeCheck.Depends: toTyDecl :: FromDecl d => d -> Maybe TyDecl
- Cryptol.TypeCheck.Infer: inferDs :: FromDecl d => [d] -> ([DeclGroup] -> InferM a) -> InferM a
- Cryptol.TypeCheck.Monad: IsExternal :: DefLoc
- Cryptol.TypeCheck.Monad: IsLocal :: DefLoc
- Cryptol.TypeCheck.Monad: [iAbstractTypes] :: RO -> Map Name (DefLoc, AbstractType)
- Cryptol.TypeCheck.Monad: [iNewtypes] :: RO -> Map Name (DefLoc, Newtype)
- Cryptol.TypeCheck.Monad: [iParamConstraints] :: RO -> [Located Prop]
- Cryptol.TypeCheck.Monad: [iParamFuns] :: RO -> Map Name ModVParam
- Cryptol.TypeCheck.Monad: [iParamTypes] :: RO -> Map Name ModTParam
- Cryptol.TypeCheck.Monad: [iTSyns] :: RO -> Map Name (DefLoc, TySyn)
- Cryptol.TypeCheck.Monad: [inpSolverConfig] :: InferInput -> SolverConfig
- Cryptol.TypeCheck.Monad: data DefLoc
- Cryptol.TypeCheck.Monad: withDecls :: ([TySyn], Map Name Schema) -> InferM a -> InferM a
- Cryptol.TypeCheck.Monad: withNewtype :: Newtype -> InferM a -> InferM a
- Cryptol.TypeCheck.Monad: withParamFuns :: [ModVParam] -> InferM a -> InferM a
- Cryptol.TypeCheck.Monad: withParamType :: ModTParam -> InferM a -> InferM a
- Cryptol.TypeCheck.Monad: withParameterConstraints :: [Located Prop] -> InferM a -> InferM a
- Cryptol.TypeCheck.Monad: withPrimType :: AbstractType -> InferM a -> InferM a
- Cryptol.TypeCheck.Monad: withTySyn :: TySyn -> InferM a -> InferM a
- Cryptol.Utils.PP: alwaysQualify :: NameDisp
- Cryptol.Utils.PP: empty :: Doc
- Cryptol.Utils.PP: fmtModName :: ModName -> NameFormat -> Text
- Cryptol.Utils.PP: liftPJ :: Doc -> Doc
- Cryptol.Utils.PP: liftPJ1 :: (Doc -> Doc) -> Doc -> Doc
- Cryptol.Utils.PP: liftPJ2 :: (Doc -> Doc -> Doc) -> Doc -> Doc -> Doc
- Cryptol.Utils.PP: punctuate :: Doc -> [Doc] -> [Doc]
- Cryptol.Utils.PP: render :: Doc -> String
+ Cryptol.Backend: IndexBackward :: IndexDirection
+ Cryptol.Backend: IndexForward :: IndexDirection
+ Cryptol.Backend: data IndexDirection
+ Cryptol.Backend: enumerateIntBits :: Backend sym => sym -> Nat' -> SInteger sym -> SEval sym (Integer, [SBit sym])
+ Cryptol.Backend: enumerateIntBits' :: Backend sym => sym -> Integer -> SInteger sym -> SEval sym (Integer, [SBit sym])
+ Cryptol.Backend: wordRotateLeft :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Backend: wordRotateRight :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Backend: wordShiftLeft :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Backend: wordShiftRight :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Backend: wordSignedShiftRight :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Backend: wordToSignedInt :: Backend sym => sym -> SWord sym -> SEval sym (SInteger sym)
+ Cryptol.Backend.Monad: data CallStack
+ Cryptol.Backend.Monad: instance GHC.Base.Monoid Cryptol.Backend.Monad.CallStack
+ Cryptol.Backend.Monad: instance GHC.Base.Semigroup Cryptol.Backend.Monad.CallStack
+ Cryptol.Backend.SeqMap: BitIndexSegment :: SBit sym -> IndexSegment sym
+ Cryptol.Backend.SeqMap: WordIndexSegment :: SWord sym -> IndexSegment sym
+ Cryptol.Backend.SeqMap: barrelShifter :: Backend sym => sym -> (SBit sym -> a -> a -> SEval sym a) -> (SeqMap sym a -> Integer -> SEval sym (SeqMap sym a)) -> Nat' -> SeqMap sym a -> Integer -> [IndexSegment sym] -> SEval sym (SeqMap sym a)
+ Cryptol.Backend.SeqMap: concatSeqMap :: Backend sym => Integer -> SeqMap sym a -> SeqMap sym a -> SeqMap sym a
+ Cryptol.Backend.SeqMap: data IndexSegment sym
+ Cryptol.Backend.SeqMap: data SeqMap sym a
+ Cryptol.Backend.SeqMap: delaySeqMap :: Backend sym => sym -> SEval sym (SeqMap sym a) -> SEval sym (SeqMap sym a)
+ Cryptol.Backend.SeqMap: dropSeqMap :: Backend sym => Integer -> SeqMap sym a -> SeqMap sym a
+ Cryptol.Backend.SeqMap: enumerateSeqMap :: (Backend sym, Integral n) => n -> SeqMap sym a -> [SEval sym a]
+ Cryptol.Backend.SeqMap: finiteSeqMap :: Backend sym => sym -> [SEval sym a] -> SeqMap sym a
+ Cryptol.Backend.SeqMap: indexSeqMap :: (Integer -> SEval sym a) -> SeqMap sym a
+ Cryptol.Backend.SeqMap: infiniteSeqMap :: Backend sym => sym -> [SEval sym a] -> SEval sym (SeqMap sym a)
+ Cryptol.Backend.SeqMap: instance Cryptol.Backend.Backend sym => GHC.Base.Functor (Cryptol.Backend.SeqMap.SeqMap sym)
+ Cryptol.Backend.SeqMap: lookupSeqMap :: Backend sym => SeqMap sym a -> Integer -> SEval sym a
+ Cryptol.Backend.SeqMap: mapSeqMap :: Backend sym => sym -> (a -> SEval sym a) -> Nat' -> SeqMap sym a -> SEval sym (SeqMap sym a)
+ Cryptol.Backend.SeqMap: memoMap :: Backend sym => sym -> Nat' -> SeqMap sym a -> SEval sym (SeqMap sym a)
+ Cryptol.Backend.SeqMap: mergeSeqMap :: Backend sym => sym -> (SBit sym -> a -> a -> SEval sym a) -> SBit sym -> SeqMap sym a -> SeqMap sym a -> SeqMap sym a
+ Cryptol.Backend.SeqMap: reverseSeqMap :: Backend sym => Integer -> SeqMap sym a -> SeqMap sym a
+ Cryptol.Backend.SeqMap: shiftSeqByInteger :: Backend sym => sym -> (SBit sym -> a -> a -> SEval sym a) -> (Integer -> Integer -> Maybe Integer) -> SEval sym a -> Nat' -> SeqMap sym a -> SInteger sym -> SEval sym (SeqMap sym a)
+ Cryptol.Backend.SeqMap: splitSeqMap :: Backend sym => Integer -> SeqMap sym a -> (SeqMap sym a, SeqMap sym a)
+ Cryptol.Backend.SeqMap: streamSeqMap :: Backend sym => SeqMap sym a -> [SEval sym a]
+ Cryptol.Backend.SeqMap: updateSeqMap :: SeqMap sym a -> Integer -> SEval sym a -> SeqMap sym a
+ Cryptol.Backend.SeqMap: zipSeqMap :: Backend sym => sym -> (a -> a -> SEval sym a) -> Nat' -> SeqMap sym a -> SeqMap sym a -> SEval sym (SeqMap sym a)
+ Cryptol.Backend.What4: instance GHC.Base.Functor (Cryptol.Backend.What4.W4Result sym)
+ Cryptol.Backend.WordValue: asBitsMap :: Backend sym => sym -> WordValue sym -> SeqMap sym (SBit sym)
+ Cryptol.Backend.WordValue: asWordList :: forall sym. Backend sym => sym -> [WordValue sym] -> SEval sym (Maybe [SWord sym])
+ Cryptol.Backend.WordValue: asWordVal :: Backend sym => sym -> WordValue sym -> SEval sym (SWord sym)
+ Cryptol.Backend.WordValue: assertWordValueInBounds :: Backend sym => sym -> Integer -> WordValue sym -> SEval sym ()
+ Cryptol.Backend.WordValue: bitmapWordVal :: Backend sym => sym -> Integer -> SeqMap sym (SBit sym) -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: data WordValue sym
+ Cryptol.Backend.WordValue: delayWordValue :: Backend sym => sym -> Integer -> SEval sym (WordValue sym) -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: dropWordVal :: Backend sym => sym -> Integer -> Integer -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: enumerateIndexSegments :: Backend sym => sym -> WordValue sym -> SEval sym [IndexSegment sym]
+ Cryptol.Backend.WordValue: enumerateWordValue :: Backend sym => sym -> WordValue sym -> SEval sym [SBit sym]
+ Cryptol.Backend.WordValue: enumerateWordValueRev :: Backend sym => sym -> WordValue sym -> SEval sym [SBit sym]
+ Cryptol.Backend.WordValue: extractWordVal :: Backend sym => sym -> Integer -> Integer -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: forceWordValue :: Backend sym => WordValue sym -> SEval sym ()
+ Cryptol.Backend.WordValue: indexWordValue :: Backend sym => sym -> WordValue sym -> Integer -> SEval sym (SBit sym)
+ Cryptol.Backend.WordValue: instance GHC.Generics.Generic (Cryptol.Backend.WordValue.WordValue sym)
+ Cryptol.Backend.WordValue: joinWordVal :: Backend sym => sym -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: joinWords :: forall sym. Backend sym => sym -> Integer -> Integer -> SeqMap sym (WordValue sym) -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: mergeWord :: Backend sym => sym -> SBit sym -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: mergeWord' :: Backend sym => sym -> SBit sym -> SEval sym (WordValue sym) -> SEval sym (WordValue sym) -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: reverseWordVal :: Backend sym => sym -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: shiftSeqByWord :: Backend sym => sym -> (SBit sym -> a -> a -> SEval sym a) -> (Integer -> Integer -> Maybe Integer) -> SEval sym a -> Nat' -> SeqMap sym a -> WordValue sym -> SEval sym (SeqMap sym a)
+ Cryptol.Backend.WordValue: shiftWordByInteger :: Backend sym => sym -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> (Integer -> Integer -> Maybe Integer) -> WordValue sym -> SInteger sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: shiftWordByWord :: Backend sym => sym -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> (Integer -> Integer -> Maybe Integer) -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: takeWordVal :: Backend sym => sym -> Integer -> Integer -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: updateWordByWord :: Backend sym => sym -> IndexDirection -> WordValue sym -> WordValue sym -> SEval sym (SBit sym) -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: updateWordValue :: Backend sym => sym -> WordValue sym -> Integer -> SEval sym (SBit sym) -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: wordVal :: SWord sym -> WordValue sym
+ Cryptol.Backend.WordValue: wordValAsLit :: Backend sym => sym -> WordValue sym -> SEval sym (Maybe Integer)
+ Cryptol.Backend.WordValue: wordValLogicOp :: Backend sym => sym -> (SBit sym -> SBit sym -> SEval sym (SBit sym)) -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: wordValUnaryOp :: Backend sym => sym -> (SBit sym -> SEval sym (SBit sym)) -> (SWord sym -> SEval sym (SWord sym)) -> WordValue sym -> SEval sym (WordValue sym)
+ Cryptol.Backend.WordValue: wordValueEqualsInteger :: forall sym. Backend sym => sym -> WordValue sym -> Integer -> SEval sym (SBit sym)
+ Cryptol.Backend.WordValue: wordValueSize :: Backend sym => sym -> WordValue sym -> Integer
+ Cryptol.Eval: [useFieldOrder] :: PPOpts -> FieldOrder
+ Cryptol.Eval.Generic: dropV :: Backend sym => sym -> Integer -> Nat' -> TValue -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
+ Cryptol.Eval.Generic: fromToByLessThanV :: Backend sym => sym -> Prim sym
+ Cryptol.Eval.Generic: fromToByV :: Backend sym => sym -> Prim sym
+ Cryptol.Eval.Generic: fromToDownByGreaterThanV :: Backend sym => sym -> Prim sym
+ Cryptol.Eval.Generic: fromToDownByV :: Backend sym => sym -> Prim sym
+ Cryptol.Eval.Generic: splitV :: Backend sym => sym -> Nat' -> Integer -> TValue -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
+ Cryptol.Eval.Generic: sshrV :: Backend sym => sym -> Prim sym
+ Cryptol.Eval.Generic: takeV :: Backend sym => sym -> Nat' -> Nat' -> TValue -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
+ Cryptol.Eval.Generic: toSignedIntegerV :: Backend sym => sym -> Prim sym
+ Cryptol.Eval.Value: instance GHC.Show.Show (Cryptol.Eval.Value.GenValue sym)
+ Cryptol.Eval.Value: iteValue :: Backend sym => sym -> SBit sym -> SEval sym (GenValue sym) -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
+ Cryptol.Eval.Value: mergeValue :: Backend sym => sym -> SBit sym -> GenValue sym -> GenValue sym -> SEval sym (GenValue sym)
+ Cryptol.Eval.Value: wordRotateLeft :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Eval.Value: wordRotateRight :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Eval.Value: wordShiftLeft :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Eval.Value: wordShiftRight :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Eval.Value: wordSignedShiftRight :: Backend sym => sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)
+ Cryptol.Eval.Value: wordToSignedInt :: Backend sym => sym -> SWord sym -> SEval sym (SInteger sym)
+ Cryptol.ModuleSystem: [deTySyns] :: DynamicEnv -> Map Name TySyn
+ Cryptol.ModuleSystem: [ifModules] :: IfaceDecls -> !Map Name (IfaceG Name)
+ Cryptol.ModuleSystem: data IfaceG mname
+ Cryptol.ModuleSystem: type Iface = IfaceG ModName
+ Cryptol.ModuleSystem.Env: [deTySyns] :: DynamicEnv -> Map Name TySyn
+ Cryptol.ModuleSystem.Env: [lmNamingEnv] :: LoadedModule -> !NamingEnv
+ Cryptol.ModuleSystem.Env: [mctxExported] :: ModContext -> Set Name
+ Cryptol.ModuleSystem.Env: dynModContext :: ModuleEnv -> ModContext
+ Cryptol.ModuleSystem.Env: instance GHC.Base.Monoid Cryptol.ModuleSystem.Env.ModContext
+ Cryptol.ModuleSystem.Env: instance GHC.Base.Semigroup Cryptol.ModuleSystem.Env.ModContext
+ Cryptol.ModuleSystem.Env: modContextOf :: ModName -> ModuleEnv -> Maybe ModContext
+ Cryptol.ModuleSystem.Exports: exportName :: Ord name => Namespace -> TopLevel name -> ExportSpec name
+ Cryptol.ModuleSystem.Exports: exported :: Namespace -> ExportSpec name -> Set name
+ Cryptol.ModuleSystem.Exports: exportedNames :: Ord name => TopDecl name -> [ExportSpec name]
+ Cryptol.ModuleSystem.Exports: isExported :: Ord name => Namespace -> name -> ExportSpec name -> Bool
+ Cryptol.ModuleSystem.Exports: names :: (a -> ([Located a'], b)) -> TopLevel a -> [TopLevel a']
+ Cryptol.ModuleSystem.Exports: newtype ExportSpec name
+ Cryptol.ModuleSystem.Interface: [ifModules] :: IfaceDecls -> !Map Name (IfaceG Name)
+ Cryptol.ModuleSystem.Interface: data IfaceG mname
+ Cryptol.ModuleSystem.Interface: emptyIface :: mname -> IfaceG mname
+ Cryptol.ModuleSystem.Interface: filterIfaceDecls :: (Name -> Bool) -> IfaceDecls -> IfaceDecls
+ Cryptol.ModuleSystem.Interface: flatPublicDecls :: IfaceDecls -> IfaceDecls
+ Cryptol.ModuleSystem.Interface: flatPublicIface :: IfaceG mname -> IfaceDecls
+ Cryptol.ModuleSystem.Interface: ifaceDeclsNames :: IfaceDecls -> Set Name
+ Cryptol.ModuleSystem.Interface: ifaceIsFunctor :: IfaceG mname -> Bool
+ 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.Show.Show mname => GHC.Show.Show (Cryptol.ModuleSystem.Interface.IfaceG mname)
+ Cryptol.ModuleSystem.Interface: isEmptyIfaceParams :: IfaceParams -> Bool
+ Cryptol.ModuleSystem.Interface: type Iface = IfaceG ModName
+ Cryptol.ModuleSystem.Monad: getIfaces :: ModuleM (ModName -> Iface)
+ Cryptol.ModuleSystem.Name: NSModule :: Namespace
+ Cryptol.ModuleSystem.Name: NSType :: Namespace
+ Cryptol.ModuleSystem.Name: NSValue :: Namespace
+ Cryptol.ModuleSystem.Name: Nested :: ModPath -> Ident -> ModPath
+ Cryptol.ModuleSystem.Name: TopModule :: ModName -> ModPath
+ Cryptol.ModuleSystem.Name: asOrigName :: Name -> Maybe OrigName
+ Cryptol.ModuleSystem.Name: data ModPath
+ Cryptol.ModuleSystem.Name: data Namespace
+ Cryptol.ModuleSystem.Name: nameNamespace :: Name -> Namespace
+ Cryptol.ModuleSystem.NamingEnv: buildNamingEnv :: BuildNamingEnv -> Supply -> (NamingEnv, Supply)
+ 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: defsOf :: BindsNames a => a -> Supply -> (NamingEnv, Supply)
+ 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.Utils.PP.PP Cryptol.ModuleSystem.NamingEnv.NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: interpImportEnv :: ImportG name -> NamingEnv -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: interpImportIface :: Import -> IfaceDecls -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: lookupNS :: Namespace -> PName -> NamingEnv -> [Name]
+ Cryptol.ModuleSystem.NamingEnv: moduleDefs :: ModPath -> ModuleG mname PName -> BuildNamingEnv
+ Cryptol.ModuleSystem.NamingEnv: namespaceMap :: Namespace -> NamingEnv -> Map PName [Name]
+ Cryptol.ModuleSystem.NamingEnv: namingEnvNames :: NamingEnv -> Set Name
+ Cryptol.ModuleSystem.NamingEnv: namingEnvRename :: (Name -> Name) -> NamingEnv -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: newtype NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: singletonNS :: Namespace -> PName -> Name -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: type CollectM = StateT NestedMods (SupplyT Id)
+ Cryptol.ModuleSystem.NamingEnv: type NestedMods = Map Name NamingEnv
+ Cryptol.ModuleSystem.Renamer: InvalidDependency :: [DepName] -> RenamerError
+ Cryptol.ModuleSystem.Renamer: NameBind :: NameType
+ Cryptol.ModuleSystem.Renamer: NameUse :: NameType
+ Cryptol.ModuleSystem.Renamer: RenamedModule :: Module Name -> NamingEnv -> NamingEnv -> IfaceDecls -> RenamedModule
+ Cryptol.ModuleSystem.Renamer: RenamerInfo :: Supply -> ModPath -> NamingEnv -> (ModName -> Iface) -> RenamerInfo
+ Cryptol.ModuleSystem.Renamer: UnboundName :: Namespace -> Located PName -> RenamerError
+ Cryptol.ModuleSystem.Renamer: WrongNamespace :: Namespace -> Namespace -> Located PName -> RenamerError
+ Cryptol.ModuleSystem.Renamer: [renContext] :: RenamerInfo -> ModPath
+ Cryptol.ModuleSystem.Renamer: [renEnv] :: RenamerInfo -> NamingEnv
+ Cryptol.ModuleSystem.Renamer: [renIfaces] :: RenamerInfo -> ModName -> Iface
+ Cryptol.ModuleSystem.Renamer: [renSupply] :: RenamerInfo -> Supply
+ Cryptol.ModuleSystem.Renamer: [rmDefines] :: RenamedModule -> NamingEnv
+ Cryptol.ModuleSystem.Renamer: [rmImported] :: RenamedModule -> IfaceDecls
+ Cryptol.ModuleSystem.Renamer: [rmInScope] :: RenamedModule -> NamingEnv
+ Cryptol.ModuleSystem.Renamer: [rmModule] :: RenamedModule -> Module Name
+ Cryptol.ModuleSystem.Renamer: data NameType
+ Cryptol.ModuleSystem.Renamer: data RenamedModule
+ Cryptol.ModuleSystem.Renamer: data RenamerInfo
+ 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: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.ImpName
+ Cryptol.ModuleSystem.Renamer: renameTopDecls :: ModName -> [TopDecl PName] -> RenameM (NamingEnv, [TopDecl Name])
+ Cryptol.ModuleSystem.Renamer.Error: BoundReservedType :: PName -> Maybe Range -> Doc -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: ConstratintAt :: Range -> DepName
+ Cryptol.ModuleSystem.Renamer.Error: FixityError :: Located Name -> Fixity -> Located Name -> Fixity -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: InvalidConstraint :: Type PName -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: InvalidDependency :: [DepName] -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: MalformedBuiltin :: Type PName -> PName -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: MultipleSyms :: Located PName -> [Name] -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: NamedThing :: Name -> DepName
+ Cryptol.ModuleSystem.Renamer.Error: OverlappingRecordUpdate :: Located [Selector] -> Located [Selector] -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: OverlappingSyms :: [Name] -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: SymbolShadowed :: PName -> Name -> [Name] -> RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: UnboundName :: Namespace -> Located PName -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: UnusedName :: Name -> RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: WrongNamespace :: Namespace -> Namespace -> Located PName -> RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: data DepName
+ Cryptol.ModuleSystem.Renamer.Error: data RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: data RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: depNameLoc :: DepName -> Range
+ Cryptol.ModuleSystem.Renamer.Error: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Renamer.Error.DepName
+ Cryptol.ModuleSystem.Renamer.Error: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Renamer.Error.RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: instance Control.DeepSeq.NFData Cryptol.ModuleSystem.Renamer.Error.RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: instance Cryptol.Utils.PP.PP Cryptol.ModuleSystem.Renamer.Error.DepName
+ Cryptol.ModuleSystem.Renamer.Error: instance Cryptol.Utils.PP.PP Cryptol.ModuleSystem.Renamer.Error.RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: instance Cryptol.Utils.PP.PP Cryptol.ModuleSystem.Renamer.Error.RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Classes.Eq Cryptol.ModuleSystem.Renamer.Error.DepName
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Classes.Eq Cryptol.ModuleSystem.Renamer.Error.RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Classes.Ord Cryptol.ModuleSystem.Renamer.Error.DepName
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Classes.Ord Cryptol.ModuleSystem.Renamer.Error.RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Generics.Generic Cryptol.ModuleSystem.Renamer.Error.DepName
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Generics.Generic Cryptol.ModuleSystem.Renamer.Error.RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Generics.Generic Cryptol.ModuleSystem.Renamer.Error.RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Show.Show Cryptol.ModuleSystem.Renamer.Error.DepName
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Show.Show Cryptol.ModuleSystem.Renamer.Error.RenamerError
+ Cryptol.ModuleSystem.Renamer.Error: instance GHC.Show.Show Cryptol.ModuleSystem.Renamer.Error.RenamerWarning
+ Cryptol.ModuleSystem.Renamer.Monad: CheckAll :: EnvCheck
+ Cryptol.ModuleSystem.Renamer.Monad: CheckNone :: EnvCheck
+ Cryptol.ModuleSystem.Renamer.Monad: CheckOverlap :: EnvCheck
+ Cryptol.ModuleSystem.Renamer.Monad: NameBind :: NameType
+ Cryptol.ModuleSystem.Renamer.Monad: NameUse :: NameType
+ Cryptol.ModuleSystem.Renamer.Monad: RO :: Range -> NamingEnv -> (ModName -> Iface) -> ModPath -> Map ModPath Name -> 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: RenameM :: ReaderT RO (StateT RW Lift) a -> RenameM a
+ Cryptol.ModuleSystem.Renamer.Monad: RenamerInfo :: Supply -> ModPath -> NamingEnv -> (ModName -> Iface) -> RenamerInfo
+ Cryptol.ModuleSystem.Renamer.Monad: [renContext] :: RenamerInfo -> ModPath
+ Cryptol.ModuleSystem.Renamer.Monad: [renEnv] :: RenamerInfo -> NamingEnv
+ Cryptol.ModuleSystem.Renamer.Monad: [renIfaces] :: RenamerInfo -> ModName -> Iface
+ Cryptol.ModuleSystem.Renamer.Monad: [renSupply] :: RenamerInfo -> Supply
+ Cryptol.ModuleSystem.Renamer.Monad: [roCurMod] :: RO -> ModPath
+ Cryptol.ModuleSystem.Renamer.Monad: [roIfaces] :: RO -> ModName -> Iface
+ Cryptol.ModuleSystem.Renamer.Monad: [roLoc] :: RO -> Range
+ Cryptol.ModuleSystem.Renamer.Monad: [roNames] :: RO -> NamingEnv
+ Cryptol.ModuleSystem.Renamer.Monad: [roNestedMods] :: RO -> Map ModPath Name
+ Cryptol.ModuleSystem.Renamer.Monad: [rwCurrentDeps] :: RW -> Set Name
+ Cryptol.ModuleSystem.Renamer.Monad: [rwDepGraph] :: RW -> Map DepName (Set Name)
+ Cryptol.ModuleSystem.Renamer.Monad: [rwErrors] :: RW -> !Seq RenamerError
+ Cryptol.ModuleSystem.Renamer.Monad: [rwExternalDeps] :: RW -> !IfaceDecls
+ Cryptol.ModuleSystem.Renamer.Monad: [rwNameUseCount] :: RW -> !Map Name Int
+ Cryptol.ModuleSystem.Renamer.Monad: [rwSupply] :: RW -> !Supply
+ Cryptol.ModuleSystem.Renamer.Monad: [rwWarnings] :: RW -> ![RenamerWarning]
+ Cryptol.ModuleSystem.Renamer.Monad: [unRenameM] :: RenameM a -> ReaderT RO (StateT RW Lift) a
+ Cryptol.ModuleSystem.Renamer.Monad: addDep :: Name -> RenameM ()
+ Cryptol.ModuleSystem.Renamer.Monad: checkEnv :: EnvCheck -> NamingEnv -> NamingEnv -> RW -> (NamingEnv, RW)
+ Cryptol.ModuleSystem.Renamer.Monad: collectIfaceDeps :: RenameM a -> RenameM (IfaceDecls, a)
+ Cryptol.ModuleSystem.Renamer.Monad: containsOverlap :: [Name] -> Seq RenamerError
+ Cryptol.ModuleSystem.Renamer.Monad: curLoc :: RenameM Range
+ Cryptol.ModuleSystem.Renamer.Monad: data EnvCheck
+ Cryptol.ModuleSystem.Renamer.Monad: data NameType
+ Cryptol.ModuleSystem.Renamer.Monad: data RO
+ Cryptol.ModuleSystem.Renamer.Monad: data RW
+ Cryptol.ModuleSystem.Renamer.Monad: data RenamerInfo
+ Cryptol.ModuleSystem.Renamer.Monad: depGroup :: RenameM a -> RenameM (a, Map DepName (Set Name))
+ Cryptol.ModuleSystem.Renamer.Monad: depsOf :: DepName -> RenameM a -> RenameM a
+ Cryptol.ModuleSystem.Renamer.Monad: getCurMod :: RenameM ModPath
+ Cryptol.ModuleSystem.Renamer.Monad: getNamingEnv :: RenameM NamingEnv
+ Cryptol.ModuleSystem.Renamer.Monad: instance (GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (Cryptol.ModuleSystem.Renamer.Monad.RenameM a)
+ Cryptol.ModuleSystem.Renamer.Monad: instance Cryptol.ModuleSystem.Name.FreshM Cryptol.ModuleSystem.Renamer.Monad.RenameM
+ Cryptol.ModuleSystem.Renamer.Monad: instance GHC.Base.Applicative Cryptol.ModuleSystem.Renamer.Monad.RenameM
+ Cryptol.ModuleSystem.Renamer.Monad: instance GHC.Base.Functor Cryptol.ModuleSystem.Renamer.Monad.RenameM
+ Cryptol.ModuleSystem.Renamer.Monad: instance GHC.Base.Monad Cryptol.ModuleSystem.Renamer.Monad.RenameM
+ Cryptol.ModuleSystem.Renamer.Monad: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Cryptol.ModuleSystem.Renamer.Monad.RenameM a)
+ Cryptol.ModuleSystem.Renamer.Monad: instance GHC.Classes.Eq Cryptol.ModuleSystem.Renamer.Monad.EnvCheck
+ Cryptol.ModuleSystem.Renamer.Monad: instance GHC.Show.Show Cryptol.ModuleSystem.Renamer.Monad.EnvCheck
+ Cryptol.ModuleSystem.Renamer.Monad: located :: a -> RenameM (Located a)
+ Cryptol.ModuleSystem.Renamer.Monad: lookupImport :: Import -> RenameM IfaceDecls
+ Cryptol.ModuleSystem.Renamer.Monad: nestedModuleOrig :: ModPath -> RenameM (Maybe Name)
+ Cryptol.ModuleSystem.Renamer.Monad: newtype RenameM a
+ Cryptol.ModuleSystem.Renamer.Monad: record :: RenamerError -> RenameM ()
+ Cryptol.ModuleSystem.Renamer.Monad: recordUse :: Name -> RenameM ()
+ Cryptol.ModuleSystem.Renamer.Monad: runRenamer :: RenamerInfo -> RenameM a -> (Either [RenamerError] (a, Supply), [RenamerWarning])
+ Cryptol.ModuleSystem.Renamer.Monad: setCurMod :: ModPath -> RenameM a -> RenameM a
+ Cryptol.ModuleSystem.Renamer.Monad: setNestedModule :: Map ModPath Name -> RenameM a -> RenameM a
+ Cryptol.ModuleSystem.Renamer.Monad: shadowNames :: BindsNames env => env -> RenameM a -> RenameM a
+ Cryptol.ModuleSystem.Renamer.Monad: shadowNames' :: BindsNames env => EnvCheck -> env -> RenameM a -> RenameM a
+ Cryptol.ModuleSystem.Renamer.Monad: warnUnused :: ModPath -> NamingEnv -> RW -> [RenamerWarning]
+ Cryptol.ModuleSystem.Renamer.Monad: withLoc :: HasLoc loc => loc -> RenameM a -> RenameM a
+ Cryptol.Parser.AST: DImport :: Located (ImportG (ImpName name)) -> TopDecl name
+ Cryptol.Parser.AST: DModule :: TopLevel (NestedModule name) -> TopDecl name
+ Cryptol.Parser.AST: DRec :: [Bind name] -> Decl name
+ Cryptol.Parser.AST: EFromToBy :: Bool -> Type n -> Type n -> Type n -> Maybe (Type n) -> Expr n
+ Cryptol.Parser.AST: EFromToDownBy :: Bool -> Type n -> Type n -> Type n -> Maybe (Type n) -> Expr n
+ Cryptol.Parser.AST: ImpNested :: name -> ImpName name
+ Cryptol.Parser.AST: ImpTop :: ModName -> ImpName name
+ Cryptol.Parser.AST: NestedModule :: ModuleG name name -> NestedModule name
+ Cryptol.Parser.AST: [bExport] :: Bind name -> !ExportType
+ Cryptol.Parser.AST: data ImpName name
+ Cryptol.Parser.AST: data ImportG mname
+ Cryptol.Parser.AST: data ModuleG mname name
+ Cryptol.Parser.AST: instance (Control.DeepSeq.NFData mname, Control.DeepSeq.NFData name) => Control.DeepSeq.NFData (Cryptol.Parser.AST.ModuleG mname name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show mname, GHC.Show.Show name) => GHC.Show.Show (Cryptol.Parser.AST.ModuleG mname name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName mname, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ModuleG mname name)
+ Cryptol.Parser.AST: instance (GHC.Show.Show name, Cryptol.Utils.PP.PPName name) => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.NestedModule name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData mname => Control.DeepSeq.NFData (Cryptol.Parser.AST.ImportG mname)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.ImpName name)
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData name => Control.DeepSeq.NFData (Cryptol.Parser.AST.NestedModule name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.ModuleG mname name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.AST.NoPos (Cryptol.Parser.AST.NestedModule name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.Position.HasLoc (Cryptol.Parser.AST.ModuleG mname name)
+ Cryptol.Parser.AST: instance Cryptol.Parser.Position.HasLoc (Cryptol.Parser.AST.NestedModule name)
+ Cryptol.Parser.AST: instance Cryptol.Utils.PP.PP mname => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ImportG mname)
+ Cryptol.Parser.AST: instance Cryptol.Utils.PP.PP name => Cryptol.Utils.PP.PP (Cryptol.Parser.AST.ImpName name)
+ Cryptol.Parser.AST: instance GHC.Classes.Eq mname => GHC.Classes.Eq (Cryptol.Parser.AST.ImportG mname)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ImpName name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ImportG mname)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.ModuleG mname name)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.NestedModule name)
+ Cryptol.Parser.AST: instance GHC.Show.Show mname => GHC.Show.Show (Cryptol.Parser.AST.ImportG mname)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.ImpName name)
+ Cryptol.Parser.AST: instance GHC.Show.Show name => GHC.Show.Show (Cryptol.Parser.AST.NestedModule name)
+ Cryptol.Parser.AST: mImports :: ModuleG mname name -> [Located Import]
+ Cryptol.Parser.AST: mSubmoduleImports :: ModuleG mname name -> [Located (ImportG name)]
+ Cryptol.Parser.AST: newtype NestedModule name
+ Cryptol.Parser.AST: type Import = ImportG ModName
+ Cryptol.Parser.AST: type Module = ModuleG ModName
+ Cryptol.Parser.Layout: Explicit :: TokenT -> Block
+ Cryptol.Parser.Layout: Virtual :: Int -> Block
+ Cryptol.Parser.Layout: data Block
+ Cryptol.Parser.Layout: endsLayout :: TokenT -> Bool
+ Cryptol.Parser.Layout: errTok :: Range -> TokenErr -> Located Token
+ Cryptol.Parser.Layout: instance GHC.Show.Show Cryptol.Parser.Layout.Block
+ Cryptol.Parser.Layout: layout :: Bool -> [Located Token] -> [Located Token]
+ Cryptol.Parser.Layout: startsLayout :: TokenT -> Bool
+ Cryptol.Parser.Layout: startsParenBlock :: TokenT -> Maybe TokenT
+ Cryptol.Parser.Layout: virt :: Range -> TokenV -> Located Token
+ Cryptol.Parser.Lexer: DotDotGt :: TokenSym
+ Cryptol.Parser.Lexer: Gt :: TokenSym
+ Cryptol.Parser.Lexer: InvalidIndentation :: TokenT -> TokenErr
+ Cryptol.Parser.Lexer: KW_by :: TokenKW
+ Cryptol.Parser.Lexer: KW_down :: TokenKW
+ Cryptol.Parser.Lexer: KW_submodule :: TokenKW
+ Cryptol.Parser.Lexer: dbgLex :: FilePath -> IO ()
+ Cryptol.Parser.NoPat: instance Cryptol.Parser.NoPat.RemovePatterns (Cryptol.Parser.AST.ModuleG mname Cryptol.Parser.Name.PName)
+ Cryptol.Parser.NoPat: instance Cryptol.Parser.NoPat.RemovePatterns (Cryptol.Parser.AST.NestedModule Cryptol.Parser.Name.PName)
+ Cryptol.Parser.Position: instance Data.Foldable.Foldable Cryptol.Parser.Position.Located
+ Cryptol.Parser.Position: instance Data.Traversable.Traversable Cryptol.Parser.Position.Located
+ Cryptol.Parser.Token: ArrL :: TokenSym
+ Cryptol.Parser.Token: ArrR :: TokenSym
+ Cryptol.Parser.Token: At :: TokenOp
+ Cryptol.Parser.Token: BackTick :: TokenSym
+ Cryptol.Parser.Token: Bar :: TokenSym
+ Cryptol.Parser.Token: BlockComment :: TokenW
+ Cryptol.Parser.Token: BracketL :: TokenSym
+ Cryptol.Parser.Token: BracketR :: TokenSym
+ Cryptol.Parser.Token: ChrLit :: !Char -> TokenT
+ Cryptol.Parser.Token: Colon :: TokenSym
+ Cryptol.Parser.Token: Comma :: TokenSym
+ Cryptol.Parser.Token: Complement :: TokenOp
+ Cryptol.Parser.Token: CurlyL :: TokenSym
+ Cryptol.Parser.Token: CurlyR :: TokenSym
+ Cryptol.Parser.Token: Div :: TokenOp
+ Cryptol.Parser.Token: DocStr :: TokenW
+ Cryptol.Parser.Token: Dot :: TokenSym
+ Cryptol.Parser.Token: DotDot :: TokenSym
+ Cryptol.Parser.Token: DotDotDot :: TokenSym
+ Cryptol.Parser.Token: DotDotGt :: TokenSym
+ Cryptol.Parser.Token: DotDotLt :: TokenSym
+ Cryptol.Parser.Token: EOF :: TokenT
+ Cryptol.Parser.Token: EqDef :: TokenSym
+ Cryptol.Parser.Token: Equal :: TokenOp
+ Cryptol.Parser.Token: Err :: !TokenErr -> TokenT
+ Cryptol.Parser.Token: Exp :: TokenOp
+ Cryptol.Parser.Token: FatArrR :: TokenSym
+ Cryptol.Parser.Token: Frac :: !Rational -> !Int -> TokenT
+ Cryptol.Parser.Token: GEQ :: TokenOp
+ Cryptol.Parser.Token: Gt :: TokenSym
+ Cryptol.Parser.Token: Hash :: TokenOp
+ Cryptol.Parser.Token: Ident :: ![Text] -> !Text -> TokenT
+ Cryptol.Parser.Token: InvalidChar :: TokenErr
+ Cryptol.Parser.Token: InvalidIndentation :: TokenT -> TokenErr
+ Cryptol.Parser.Token: InvalidString :: TokenErr
+ Cryptol.Parser.Token: KW :: !TokenKW -> TokenT
+ Cryptol.Parser.Token: KW_Prop :: TokenKW
+ Cryptol.Parser.Token: KW_as :: TokenKW
+ Cryptol.Parser.Token: KW_by :: TokenKW
+ Cryptol.Parser.Token: KW_constraint :: TokenKW
+ Cryptol.Parser.Token: KW_down :: TokenKW
+ Cryptol.Parser.Token: KW_else :: TokenKW
+ Cryptol.Parser.Token: KW_extern :: TokenKW
+ Cryptol.Parser.Token: KW_fin :: TokenKW
+ Cryptol.Parser.Token: KW_hiding :: TokenKW
+ Cryptol.Parser.Token: KW_if :: TokenKW
+ Cryptol.Parser.Token: KW_import :: TokenKW
+ Cryptol.Parser.Token: KW_include :: TokenKW
+ Cryptol.Parser.Token: KW_inf :: TokenKW
+ Cryptol.Parser.Token: KW_infix :: TokenKW
+ Cryptol.Parser.Token: KW_infixl :: TokenKW
+ Cryptol.Parser.Token: KW_infixr :: TokenKW
+ Cryptol.Parser.Token: KW_lengthFromThen :: TokenKW
+ Cryptol.Parser.Token: KW_lengthFromThenTo :: TokenKW
+ Cryptol.Parser.Token: KW_let :: TokenKW
+ Cryptol.Parser.Token: KW_lg2 :: TokenKW
+ Cryptol.Parser.Token: KW_max :: TokenKW
+ Cryptol.Parser.Token: KW_min :: TokenKW
+ Cryptol.Parser.Token: KW_module :: TokenKW
+ Cryptol.Parser.Token: KW_newtype :: TokenKW
+ Cryptol.Parser.Token: KW_parameter :: TokenKW
+ Cryptol.Parser.Token: KW_pragma :: TokenKW
+ Cryptol.Parser.Token: KW_primitive :: TokenKW
+ Cryptol.Parser.Token: KW_private :: TokenKW
+ Cryptol.Parser.Token: KW_property :: TokenKW
+ Cryptol.Parser.Token: KW_submodule :: TokenKW
+ Cryptol.Parser.Token: KW_then :: TokenKW
+ Cryptol.Parser.Token: KW_type :: TokenKW
+ Cryptol.Parser.Token: KW_where :: TokenKW
+ Cryptol.Parser.Token: KW_x :: TokenKW
+ Cryptol.Parser.Token: LEQ :: TokenOp
+ Cryptol.Parser.Token: Lambda :: TokenSym
+ Cryptol.Parser.Token: LexicalError :: TokenErr
+ Cryptol.Parser.Token: LineComment :: TokenW
+ Cryptol.Parser.Token: Lt :: TokenSym
+ Cryptol.Parser.Token: MalformedLiteral :: TokenErr
+ Cryptol.Parser.Token: MalformedSelector :: TokenErr
+ Cryptol.Parser.Token: Minus :: TokenOp
+ Cryptol.Parser.Token: Mod :: TokenOp
+ Cryptol.Parser.Token: Mul :: TokenOp
+ Cryptol.Parser.Token: Num :: !Integer -> !Int -> !Int -> TokenT
+ Cryptol.Parser.Token: Op :: !TokenOp -> TokenT
+ Cryptol.Parser.Token: Other :: [Text] -> Text -> TokenOp
+ Cryptol.Parser.Token: ParenL :: TokenSym
+ Cryptol.Parser.Token: ParenR :: TokenSym
+ Cryptol.Parser.Token: Plus :: TokenOp
+ Cryptol.Parser.Token: RecordSelectorTok :: Text -> SelectorType
+ Cryptol.Parser.Token: Selector :: !SelectorType -> TokenT
+ Cryptol.Parser.Token: Semi :: TokenSym
+ Cryptol.Parser.Token: Space :: TokenW
+ Cryptol.Parser.Token: StrLit :: !String -> TokenT
+ Cryptol.Parser.Token: Sym :: !TokenSym -> TokenT
+ Cryptol.Parser.Token: Token :: !TokenT -> !Text -> Token
+ Cryptol.Parser.Token: TriL :: TokenSym
+ Cryptol.Parser.Token: TriR :: TokenSym
+ Cryptol.Parser.Token: TupleSelectorTok :: Int -> SelectorType
+ Cryptol.Parser.Token: Underscore :: TokenSym
+ Cryptol.Parser.Token: UnterminatedChar :: TokenErr
+ Cryptol.Parser.Token: UnterminatedComment :: TokenErr
+ Cryptol.Parser.Token: UnterminatedString :: TokenErr
+ Cryptol.Parser.Token: VCurlyL :: TokenV
+ Cryptol.Parser.Token: VCurlyR :: TokenV
+ Cryptol.Parser.Token: VSemi :: TokenV
+ Cryptol.Parser.Token: Virt :: !TokenV -> TokenT
+ Cryptol.Parser.Token: White :: !TokenW -> TokenT
+ Cryptol.Parser.Token: [tokenText] :: Token -> !Text
+ Cryptol.Parser.Token: [tokenType] :: Token -> !TokenT
+ Cryptol.Parser.Token: data SelectorType
+ Cryptol.Parser.Token: data Token
+ Cryptol.Parser.Token: data TokenErr
+ Cryptol.Parser.Token: data TokenKW
+ Cryptol.Parser.Token: data TokenOp
+ Cryptol.Parser.Token: data TokenSym
+ Cryptol.Parser.Token: data TokenT
+ Cryptol.Parser.Token: data TokenV
+ Cryptol.Parser.Token: data TokenW
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.SelectorType
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.Token
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.TokenErr
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.TokenKW
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.TokenOp
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.TokenSym
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.TokenT
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.TokenV
+ Cryptol.Parser.Token: instance Control.DeepSeq.NFData Cryptol.Parser.Token.TokenW
+ Cryptol.Parser.Token: instance Cryptol.Utils.PP.PP Cryptol.Parser.Token.Token
+ Cryptol.Parser.Token: instance GHC.Classes.Eq Cryptol.Parser.Token.SelectorType
+ Cryptol.Parser.Token: instance GHC.Classes.Eq Cryptol.Parser.Token.TokenErr
+ Cryptol.Parser.Token: instance GHC.Classes.Eq Cryptol.Parser.Token.TokenKW
+ Cryptol.Parser.Token: instance GHC.Classes.Eq Cryptol.Parser.Token.TokenOp
+ Cryptol.Parser.Token: instance GHC.Classes.Eq Cryptol.Parser.Token.TokenSym
+ Cryptol.Parser.Token: instance GHC.Classes.Eq Cryptol.Parser.Token.TokenT
+ Cryptol.Parser.Token: instance GHC.Classes.Eq Cryptol.Parser.Token.TokenV
+ Cryptol.Parser.Token: instance GHC.Classes.Eq Cryptol.Parser.Token.TokenW
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.SelectorType
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.Token
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.TokenErr
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.TokenKW
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.TokenOp
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.TokenSym
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.TokenT
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.TokenV
+ Cryptol.Parser.Token: instance GHC.Generics.Generic Cryptol.Parser.Token.TokenW
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.SelectorType
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.Token
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.TokenErr
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.TokenKW
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.TokenOp
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.TokenSym
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.TokenT
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.TokenV
+ Cryptol.Parser.Token: instance GHC.Show.Show Cryptol.Parser.Token.TokenW
+ Cryptol.REPL.Browse: BrowseExported :: BrowseHow
+ Cryptol.REPL.Browse: BrowseInScope :: BrowseHow
+ Cryptol.REPL.Browse: browseModContext :: BrowseHow -> ModContext -> Doc Void
+ Cryptol.REPL.Browse: data BrowseHow
+ Cryptol.REPL.Command: withRWTempFile :: String -> (Handle -> IO a) -> IO a
+ Cryptol.REPL.Monad: getTCSolver :: REPL Solver
+ Cryptol.REPL.Monad: instance Cryptol.REPL.Monad.IsEnvVal Cryptol.Utils.PP.FieldOrder
+ Cryptol.REPL.Monad: parseFieldOrder :: String -> Maybe FieldOrder
+ Cryptol.REPL.Monad: parseSearchPath :: String -> [String]
+ Cryptol.REPL.Monad: resetTCSolver :: REPL ()
+ Cryptol.Symbolic: flattenShape :: VarShape sym -> [VarShape sym] -> [VarShape sym]
+ Cryptol.Symbolic: flattenShapes :: [VarShape sym] -> [VarShape sym] -> [VarShape sym]
+ Cryptol.Symbolic.What4: instance Control.Monad.IO.Class.MonadIO Cryptol.Symbolic.What4.MultiSat
+ Cryptol.Symbolic.What4: instance GHC.Base.Applicative Cryptol.Symbolic.What4.MultiSat
+ Cryptol.Symbolic.What4: instance GHC.Base.Functor Cryptol.Symbolic.What4.MultiSat
+ Cryptol.Symbolic.What4: instance GHC.Base.Monad Cryptol.Symbolic.What4.MultiSat
+ Cryptol.TypeCheck: TemporaryError :: Doc -> Error
+ Cryptol.TypeCheck: defaultSolverConfig :: [FilePath] -> SolverConfig
+ Cryptol.TypeCheck.AST: [mFunctors] :: ModuleG mname -> Map Name (ModuleG Name)
+ Cryptol.TypeCheck.AST: [mSubModules] :: ModuleG mname -> Map Name (IfaceG Name)
+ Cryptol.TypeCheck.AST: data ImportG mname
+ Cryptol.TypeCheck.AST: data ModuleG mname
+ Cryptol.TypeCheck.AST: emptyModule :: mname -> ModuleG mname
+ Cryptol.TypeCheck.AST: instance Control.DeepSeq.NFData mname => Control.DeepSeq.NFData (Cryptol.TypeCheck.AST.ModuleG mname)
+ Cryptol.TypeCheck.AST: instance Cryptol.Utils.PP.PP n => Cryptol.Utils.PP.PP (Cryptol.TypeCheck.AST.ModuleG n)
+ Cryptol.TypeCheck.AST: instance Cryptol.Utils.PP.PP n => Cryptol.Utils.PP.PP (Cryptol.TypeCheck.PP.WithNames (Cryptol.TypeCheck.AST.ModuleG n))
+ Cryptol.TypeCheck.AST: instance GHC.Generics.Generic (Cryptol.TypeCheck.AST.ModuleG mname)
+ Cryptol.TypeCheck.AST: instance GHC.Show.Show mname => GHC.Show.Show (Cryptol.TypeCheck.AST.ModuleG mname)
+ Cryptol.TypeCheck.AST: isExported :: Ord name => Namespace -> name -> ExportSpec name -> Bool
+ Cryptol.TypeCheck.AST: newtype ExportSpec name
+ Cryptol.TypeCheck.AST: type Import = ImportG ModName
+ Cryptol.TypeCheck.AST: type Module = ModuleG ModName
+ Cryptol.TypeCheck.Error: TemporaryError :: Doc -> Error
+ Cryptol.TypeCheck.Infer: checkTopDecls :: [TopDecl Name] -> InferM ()
+ Cryptol.TypeCheck.InferTypes: defaultSolverConfig :: [FilePath] -> SolverConfig
+ Cryptol.TypeCheck.Interface: genIface :: ModuleG mname -> IfaceG mname
+ Cryptol.TypeCheck.Interface: mkIfaceDecl :: Decl -> IfaceDecl
+ Cryptol.TypeCheck.Monad: ExternalScope :: ScopeName
+ Cryptol.TypeCheck.Monad: LocalScope :: ScopeName
+ Cryptol.TypeCheck.Monad: MTopModule :: ModName -> ScopeName
+ Cryptol.TypeCheck.Monad: SubModule :: Name -> ScopeName
+ Cryptol.TypeCheck.Monad: [iBindTypes] :: RW -> !Map Name Schema
+ Cryptol.TypeCheck.Monad: [iExtScope] :: RO -> ModuleG ScopeName
+ Cryptol.TypeCheck.Monad: [iScope] :: RW -> ![ModuleG ScopeName]
+ Cryptol.TypeCheck.Monad: addDecls :: DeclGroup -> InferM ()
+ Cryptol.TypeCheck.Monad: addNewtype :: Newtype -> InferM ()
+ Cryptol.TypeCheck.Monad: addParamFun :: ModVParam -> InferM ()
+ Cryptol.TypeCheck.Monad: addParamType :: ModTParam -> InferM ()
+ Cryptol.TypeCheck.Monad: addParameterConstraints :: [Located Prop] -> InferM ()
+ Cryptol.TypeCheck.Monad: addPrimType :: AbstractType -> InferM ()
+ Cryptol.TypeCheck.Monad: addTySyn :: TySyn -> InferM ()
+ Cryptol.TypeCheck.Monad: data ScopeName
+ Cryptol.TypeCheck.Monad: endLocalScope :: InferM ([DeclGroup], Map Name TySyn)
+ Cryptol.TypeCheck.Monad: endModule :: InferM Module
+ Cryptol.TypeCheck.Monad: endModuleInstance :: InferM ()
+ Cryptol.TypeCheck.Monad: endSubmodule :: InferM ()
+ Cryptol.TypeCheck.Monad: getScope :: Semigroup a => (ModuleG ScopeName -> a) -> InferM a
+ Cryptol.TypeCheck.Monad: newLocalScope :: InferM ()
+ Cryptol.TypeCheck.Monad: newModuleScope :: ModName -> [Import] -> ExportSpec Name -> InferM ()
+ Cryptol.TypeCheck.Monad: newScope :: ScopeName -> InferM ()
+ Cryptol.TypeCheck.Monad: newSubmoduleScope :: Name -> [Import] -> ExportSpec Name -> InferM ()
+ Cryptol.TypeCheck.Monad: updScope :: (ModuleG ScopeName -> ModuleG ScopeName) -> InferM ()
+ Cryptol.TypeCheck.Parseable: ($$) :: Doc a -> Doc a -> Doc a
+ Cryptol.TypeCheck.Parseable: infixl 5 $$
+ Cryptol.TypeCheck.Parseable: int :: Int -> Doc a
+ Cryptol.TypeCheck.Parseable: text :: String -> Doc a
+ Cryptol.TypeCheck.Solver.SMT: data SolverConfig
+ Cryptol.TypeCheck.Solver.SMT: resetSolver :: Solver -> SolverConfig -> IO ()
+ Cryptol.TypeCheck.Subst: instance Cryptol.TypeCheck.Subst.TVars Cryptol.TypeCheck.Type.TySyn
+ Cryptol.TypeCheck.Subst: instance Cryptol.TypeCheck.Subst.TVars a => Cryptol.TypeCheck.Subst.TVars (Data.Map.Internal.Map k a)
+ Cryptol.TypeCheck.Type: ModTParam :: Name -> Kind -> !Int -> Maybe Text -> ModTParam
+ Cryptol.TypeCheck.Type: ModVParam :: Name -> Schema -> Maybe Text -> Maybe Fixity -> ModVParam
+ Cryptol.TypeCheck.Type: [mtpDoc] :: ModTParam -> Maybe Text
+ Cryptol.TypeCheck.Type: [mtpKind] :: ModTParam -> Kind
+ Cryptol.TypeCheck.Type: [mtpName] :: ModTParam -> Name
+ Cryptol.TypeCheck.Type: [mtpNumber] :: ModTParam -> !Int
+ Cryptol.TypeCheck.Type: [mvpDoc] :: ModVParam -> Maybe Text
+ Cryptol.TypeCheck.Type: [mvpFixity] :: ModVParam -> Maybe Fixity
+ Cryptol.TypeCheck.Type: [mvpName] :: ModVParam -> Name
+ Cryptol.TypeCheck.Type: [mvpType] :: ModVParam -> Schema
+ Cryptol.TypeCheck.Type: data ModTParam
+ Cryptol.TypeCheck.Type: data ModVParam
+ Cryptol.TypeCheck.Type: instance Control.DeepSeq.NFData Cryptol.TypeCheck.Type.ModTParam
+ Cryptol.TypeCheck.Type: instance Control.DeepSeq.NFData Cryptol.TypeCheck.Type.ModVParam
+ Cryptol.TypeCheck.Type: instance GHC.Generics.Generic Cryptol.TypeCheck.Type.ModTParam
+ Cryptol.TypeCheck.Type: instance GHC.Generics.Generic Cryptol.TypeCheck.Type.ModVParam
+ Cryptol.TypeCheck.Type: instance GHC.Show.Show Cryptol.TypeCheck.Type.ModTParam
+ Cryptol.TypeCheck.Type: instance GHC.Show.Show Cryptol.TypeCheck.Type.ModVParam
+ Cryptol.TypeCheck.Type: mtpParam :: ModTParam -> TParam
+ Cryptol.Utils.Ident: NSModule :: Namespace
+ Cryptol.Utils.Ident: NSType :: Namespace
+ Cryptol.Utils.Ident: NSValue :: Namespace
+ Cryptol.Utils.Ident: Nested :: ModPath -> Ident -> ModPath
+ Cryptol.Utils.Ident: OrigName :: Namespace -> ModPath -> Ident -> OrigName
+ Cryptol.Utils.Ident: TopModule :: ModName -> ModPath
+ Cryptol.Utils.Ident: [ogModule] :: OrigName -> ModPath
+ Cryptol.Utils.Ident: [ogName] :: OrigName -> Ident
+ Cryptol.Utils.Ident: [ogNamespace] :: OrigName -> Namespace
+ Cryptol.Utils.Ident: allNamespaces :: [Namespace]
+ Cryptol.Utils.Ident: apPathRoot :: (ModName -> ModName) -> ModPath -> ModPath
+ Cryptol.Utils.Ident: data ModPath
+ Cryptol.Utils.Ident: data Namespace
+ Cryptol.Utils.Ident: data OrigName
+ Cryptol.Utils.Ident: instance Control.DeepSeq.NFData Cryptol.Utils.Ident.ModPath
+ Cryptol.Utils.Ident: instance Control.DeepSeq.NFData Cryptol.Utils.Ident.Namespace
+ Cryptol.Utils.Ident: instance Control.DeepSeq.NFData Cryptol.Utils.Ident.OrigName
+ Cryptol.Utils.Ident: instance GHC.Classes.Eq Cryptol.Utils.Ident.ModPath
+ Cryptol.Utils.Ident: instance GHC.Classes.Eq Cryptol.Utils.Ident.Namespace
+ Cryptol.Utils.Ident: instance GHC.Classes.Eq Cryptol.Utils.Ident.OrigName
+ Cryptol.Utils.Ident: instance GHC.Classes.Ord Cryptol.Utils.Ident.ModPath
+ Cryptol.Utils.Ident: instance GHC.Classes.Ord Cryptol.Utils.Ident.Namespace
+ Cryptol.Utils.Ident: instance GHC.Classes.Ord Cryptol.Utils.Ident.OrigName
+ Cryptol.Utils.Ident: instance GHC.Enum.Bounded Cryptol.Utils.Ident.Namespace
+ Cryptol.Utils.Ident: instance GHC.Enum.Enum Cryptol.Utils.Ident.Namespace
+ Cryptol.Utils.Ident: instance GHC.Generics.Generic Cryptol.Utils.Ident.ModPath
+ Cryptol.Utils.Ident: instance GHC.Generics.Generic Cryptol.Utils.Ident.Namespace
+ Cryptol.Utils.Ident: instance GHC.Generics.Generic Cryptol.Utils.Ident.OrigName
+ Cryptol.Utils.Ident: instance GHC.Show.Show Cryptol.Utils.Ident.ModPath
+ Cryptol.Utils.Ident: instance GHC.Show.Show Cryptol.Utils.Ident.Namespace
+ Cryptol.Utils.Ident: instance GHC.Show.Show Cryptol.Utils.Ident.OrigName
+ Cryptol.Utils.Ident: modPathCommon :: ModPath -> ModPath -> Maybe (ModPath, [Ident], [Ident])
+ Cryptol.Utils.Ident: modPathSplit :: ModPath -> (ModName, [Ident])
+ Cryptol.Utils.Ident: topModuleFor :: ModPath -> ModName
+ Cryptol.Utils.PP: (</>) :: Doc -> Doc -> Doc
+ Cryptol.Utils.PP: CanonicalOrder :: FieldOrder
+ Cryptol.Utils.PP: DisplayOrder :: FieldOrder
+ Cryptol.Utils.PP: [useFieldOrder] :: PPOpts -> FieldOrder
+ Cryptol.Utils.PP: align :: Doc -> Doc
+ Cryptol.Utils.PP: commaSepFill :: [Doc] -> Doc
+ Cryptol.Utils.PP: data FieldOrder
+ Cryptol.Utils.PP: group :: Doc -> Doc
+ Cryptol.Utils.PP: indent :: Int -> Doc -> Doc
+ Cryptol.Utils.PP: instance Cryptol.Utils.PP.PP Cryptol.Utils.Ident.ModPath
+ Cryptol.Utils.PP: instance Cryptol.Utils.PP.PP Cryptol.Utils.Ident.Namespace
+ Cryptol.Utils.PP: instance Cryptol.Utils.PP.PP Cryptol.Utils.Ident.OrigName
+ Cryptol.Utils.PP: instance Cryptol.Utils.PP.PPName Cryptol.Utils.Ident.ModName
+ Cryptol.Utils.PP: instance GHC.Classes.Eq Cryptol.Utils.PP.FieldOrder
+ Cryptol.Utils.PP: instance GHC.Classes.Ord Cryptol.Utils.PP.FieldOrder
+ Cryptol.Utils.PP: instance GHC.Enum.Bounded Cryptol.Utils.PP.FieldOrder
+ Cryptol.Utils.PP: instance GHC.Enum.Enum Cryptol.Utils.PP.FieldOrder
+ Cryptol.Utils.PP: instance GHC.Read.Read Cryptol.Utils.PP.FieldOrder
+ Cryptol.Utils.PP: instance GHC.Show.Show Cryptol.Utils.PP.FieldOrder
+ Cryptol.Utils.PP: liftPP :: Doc Void -> Doc
+ Cryptol.Utils.PP: liftPP1 :: (Doc Void -> Doc Void) -> Doc -> Doc
+ Cryptol.Utils.PP: liftPP2 :: (Doc Void -> Doc Void -> Doc Void) -> Doc -> Doc -> Doc
+ Cryptol.Utils.PP: ppList :: [Doc] -> Doc
+ Cryptol.Utils.PP: ppRecord :: [Doc] -> Doc
+ Cryptol.Utils.PP: ppTuple :: [Doc] -> Doc
+ Cryptol.Utils.PP: vsep :: [Doc] -> Doc
- Cryptol.Backend: isReady :: Backend sym => sym -> SEval sym a -> Bool
+ Cryptol.Backend: isReady :: Backend sym => sym -> SEval sym a -> SEval sym (Maybe a)
- Cryptol.Eval: PPOpts :: Bool -> Int -> Int -> Int -> PPFloatFormat -> PPOpts
+ Cryptol.Eval: PPOpts :: Bool -> Int -> Int -> Int -> PPFloatFormat -> FieldOrder -> PPOpts
- Cryptol.Eval.Generic: ccatV :: Backend sym => sym -> Nat' -> Nat' -> TValue -> GenValue sym -> GenValue sym -> SEval sym (GenValue sym)
+ Cryptol.Eval.Generic: ccatV :: Backend sym => sym -> Integer -> Nat' -> TValue -> SEval sym (GenValue sym) -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: indexPrim :: Backend sym => sym -> (Nat' -> TValue -> SeqMap sym -> TValue -> SInteger sym -> SEval sym (GenValue sym)) -> (Nat' -> TValue -> SeqMap sym -> TValue -> [SBit sym] -> SEval sym (GenValue sym)) -> (Nat' -> TValue -> SeqMap sym -> TValue -> SWord sym -> SEval sym (GenValue sym)) -> Prim sym
+ Cryptol.Eval.Generic: indexPrim :: Backend sym => sym -> IndexDirection -> (Nat' -> TValue -> SeqMap sym (GenValue sym) -> TValue -> SInteger sym -> SEval sym (GenValue sym)) -> (Nat' -> TValue -> SeqMap sym (GenValue sym) -> TValue -> Integer -> [IndexSegment sym] -> SEval sym (GenValue sym)) -> Prim sym
- Cryptol.Eval.Generic: intShifter :: Backend sym => sym -> String -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> (Nat' -> Integer -> Integer -> Maybe Integer) -> Nat' -> TValue -> TValue -> GenValue sym -> SInteger sym -> SEval sym (GenValue sym)
+ Cryptol.Eval.Generic: intShifter :: Backend sym => sym -> String -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> (Nat' -> Integer -> Integer -> Maybe Integer) -> Nat' -> TValue -> GenValue sym -> SInteger sym -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: joinSeq :: Backend sym => sym -> Nat' -> Integer -> TValue -> SeqMap sym -> SEval sym (GenValue sym)
+ Cryptol.Eval.Generic: joinSeq :: Backend sym => sym -> Nat' -> Integer -> TValue -> SEval sym (SeqMap sym (GenValue sym)) -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: joinV :: Backend sym => sym -> Nat' -> Integer -> TValue -> GenValue sym -> SEval sym (GenValue sym)
+ Cryptol.Eval.Generic: joinV :: Backend sym => sym -> Nat' -> Integer -> TValue -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: reverseV :: forall sym. Backend sym => sym -> GenValue sym -> SEval sym (GenValue sym)
+ Cryptol.Eval.Generic: reverseV :: forall sym. Backend sym => sym -> Integer -> TValue -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
- Cryptol.Eval.Generic: sparkParMap :: Backend sym => sym -> (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -> Integer -> SeqMap sym -> SEval sym (SeqMap sym)
+ Cryptol.Eval.Generic: sparkParMap :: Backend sym => sym -> (SEval sym a -> SEval sym (GenValue sym)) -> Integer -> SeqMap sym a -> SEval sym (SeqMap sym (GenValue sym))
- Cryptol.Eval.Generic: updatePrim :: Backend sym => sym -> (Nat' -> TValue -> WordValue sym -> Either (SInteger sym) (WordValue sym) -> SEval sym (GenValue sym) -> SEval sym (WordValue sym)) -> (Nat' -> TValue -> SeqMap sym -> Either (SInteger sym) (WordValue sym) -> SEval sym (GenValue sym) -> SEval sym (SeqMap sym)) -> Prim sym
+ Cryptol.Eval.Generic: updatePrim :: Backend sym => sym -> (Nat' -> TValue -> WordValue sym -> Either (SInteger sym) (WordValue sym) -> SEval sym (GenValue sym) -> SEval sym (WordValue sym)) -> (Nat' -> TValue -> SeqMap sym (GenValue sym) -> Either (SInteger sym) (WordValue sym) -> SEval sym (GenValue sym) -> SEval sym (SeqMap sym (GenValue sym))) -> Prim sym
- Cryptol.Eval.Value: VSeq :: !Integer -> !SeqMap sym -> GenValue sym
+ Cryptol.Eval.Value: VSeq :: !Integer -> !SeqMap sym (GenValue sym) -> GenValue sym
- Cryptol.Eval.Value: VStream :: !SeqMap sym -> GenValue sym
+ Cryptol.Eval.Value: VStream :: !SeqMap sym (GenValue sym) -> GenValue sym
- Cryptol.Eval.Value: VWord :: !Integer -> !SEval sym (WordValue sym) -> GenValue sym
+ Cryptol.Eval.Value: VWord :: !Integer -> !WordValue sym -> GenValue sym
- Cryptol.Eval.Value: asIndex :: Backend sym => sym -> String -> TValue -> GenValue sym -> SEval sym (Either (SInteger sym) (WordValue sym))
+ Cryptol.Eval.Value: asIndex :: Backend sym => sym -> String -> TValue -> GenValue sym -> Either (SInteger sym) (WordValue sym)
- Cryptol.Eval.Value: fromSeq :: Backend sym => String -> GenValue sym -> SEval sym (SeqMap sym)
+ Cryptol.Eval.Value: fromSeq :: Backend sym => String -> GenValue sym -> SEval sym (SeqMap sym (GenValue sym))
- Cryptol.Eval.Value: fromVSeq :: GenValue sym -> SeqMap sym
+ Cryptol.Eval.Value: fromVSeq :: GenValue sym -> SeqMap sym (GenValue sym)
- Cryptol.Eval.Value: fromWordVal :: Backend sym => String -> GenValue sym -> SEval sym (WordValue sym)
+ Cryptol.Eval.Value: fromWordVal :: Backend sym => String -> GenValue sym -> WordValue sym
- Cryptol.Eval.Value: isReady :: Backend sym => sym -> SEval sym a -> Bool
+ Cryptol.Eval.Value: isReady :: Backend sym => sym -> SEval sym a -> SEval sym (Maybe a)
- Cryptol.Eval.Value: mkSeq :: Backend sym => Nat' -> TValue -> SeqMap sym -> GenValue sym
+ Cryptol.Eval.Value: mkSeq :: Backend sym => sym -> Nat' -> TValue -> SeqMap sym (GenValue sym) -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: tryFromBits :: Backend sym => sym -> [SEval sym (GenValue sym)] -> Maybe (SEval sym (SWord sym))
+ Cryptol.Eval.Value: tryFromBits :: Backend sym => sym -> [SEval sym (GenValue sym)] -> SEval sym (Maybe (SWord sym))
- Cryptol.Eval.Value: word :: Backend sym => sym -> Integer -> Integer -> GenValue sym
+ Cryptol.Eval.Value: word :: Backend sym => sym -> Integer -> Integer -> SEval sym (GenValue sym)
- Cryptol.ModuleSystem: DEnv :: NamingEnv -> [DeclGroup] -> EvalEnv -> DynamicEnv
+ Cryptol.ModuleSystem: DEnv :: NamingEnv -> [DeclGroup] -> Map Name TySyn -> EvalEnv -> DynamicEnv
- Cryptol.ModuleSystem: Iface :: !ModName -> IfaceDecls -> IfaceDecls -> IfaceParams -> Iface
+ Cryptol.ModuleSystem: Iface :: !mname -> IfaceDecls -> IfaceDecls -> IfaceParams -> IfaceG mname
- Cryptol.ModuleSystem: IfaceDecls :: Map Name IfaceTySyn -> Map Name IfaceNewtype -> Map Name IfaceAbstractType -> Map Name IfaceDecl -> IfaceDecls
+ Cryptol.ModuleSystem: IfaceDecls :: Map Name IfaceTySyn -> Map Name IfaceNewtype -> Map Name IfaceAbstractType -> Map Name IfaceDecl -> !Map Name (IfaceG Name) -> IfaceDecls
- Cryptol.ModuleSystem: ModuleEnv :: LoadedModules -> NameSeeds -> SolverConfig -> EvalEnv -> CoreLint -> !Bool -> Maybe ModName -> [FilePath] -> DynamicEnv -> !Supply -> ModuleEnv
+ Cryptol.ModuleSystem: ModuleEnv :: LoadedModules -> NameSeeds -> EvalEnv -> CoreLint -> !Bool -> Maybe ModName -> [FilePath] -> DynamicEnv -> !Supply -> ModuleEnv
- Cryptol.ModuleSystem: [ifModName] :: Iface -> !ModName
+ Cryptol.ModuleSystem: [ifModName] :: IfaceG mname -> !mname
- Cryptol.ModuleSystem: [ifParams] :: Iface -> IfaceParams
+ Cryptol.ModuleSystem: [ifParams] :: IfaceG mname -> IfaceParams
- Cryptol.ModuleSystem: [ifPrivate] :: Iface -> IfaceDecls
+ Cryptol.ModuleSystem: [ifPrivate] :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem: [ifPublic] :: Iface -> IfaceDecls
+ Cryptol.ModuleSystem: [ifPublic] :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem: checkDecls :: [TopDecl PName] -> ModuleCmd (NamingEnv, [DeclGroup])
+ Cryptol.ModuleSystem: checkDecls :: [TopDecl PName] -> ModuleCmd (NamingEnv, [DeclGroup], Map Name TySyn)
- Cryptol.ModuleSystem: genIface :: Module -> Iface
+ Cryptol.ModuleSystem: genIface :: ModuleG mname -> IfaceG mname
- Cryptol.ModuleSystem.Base: checkDecls :: [TopDecl PName] -> ModuleM (NamingEnv, [DeclGroup])
+ Cryptol.ModuleSystem.Base: checkDecls :: [TopDecl PName] -> ModuleM (NamingEnv, [DeclGroup], Map Name TySyn)
- Cryptol.ModuleSystem.Base: checkModule :: ImportSource -> ModulePath -> Module PName -> ModuleM Module
+ Cryptol.ModuleSystem.Base: checkModule :: ImportSource -> ModulePath -> Module PName -> ModuleM (NamingEnv, Module)
- Cryptol.ModuleSystem.Base: checkSingleModule :: Act (Module Name) Module -> ImportSource -> ModulePath -> Module PName -> ModuleM Module
+ Cryptol.ModuleSystem.Base: checkSingleModule :: Act (Module Name) Module -> ImportSource -> ModulePath -> Module PName -> ModuleM (NamingEnv, Module)
- Cryptol.ModuleSystem.Base: declsLinter :: TCLinter [DeclGroup]
+ Cryptol.ModuleSystem.Base: declsLinter :: TCLinter ([DeclGroup], a)
- Cryptol.ModuleSystem.Base: renameModule :: Module PName -> ModuleM (IfaceDecls, NamingEnv, Module Name)
+ Cryptol.ModuleSystem.Base: renameModule :: Module PName -> ModuleM RenamedModule
- Cryptol.ModuleSystem.Env: DEnv :: NamingEnv -> [DeclGroup] -> EvalEnv -> DynamicEnv
+ Cryptol.ModuleSystem.Env: DEnv :: NamingEnv -> [DeclGroup] -> Map Name TySyn -> EvalEnv -> DynamicEnv
- Cryptol.ModuleSystem.Env: LoadedModule :: ModName -> ModulePath -> String -> Iface -> Module -> Fingerprint -> LoadedModule
+ Cryptol.ModuleSystem.Env: LoadedModule :: ModName -> ModulePath -> String -> !NamingEnv -> Iface -> Module -> Fingerprint -> LoadedModule
- Cryptol.ModuleSystem.Env: ModContext :: IfaceParams -> IfaceDecls -> NamingEnv -> NameDisp -> Map Name DeclProvenance -> Map Name DeclProvenance -> ModContext
+ Cryptol.ModuleSystem.Env: ModContext :: IfaceParams -> Set Name -> IfaceDecls -> NamingEnv -> NameDisp -> ModContext
- Cryptol.ModuleSystem.Env: ModuleEnv :: LoadedModules -> NameSeeds -> SolverConfig -> EvalEnv -> CoreLint -> !Bool -> Maybe ModName -> [FilePath] -> DynamicEnv -> !Supply -> ModuleEnv
+ Cryptol.ModuleSystem.Env: ModuleEnv :: LoadedModules -> NameSeeds -> EvalEnv -> CoreLint -> !Bool -> Maybe ModName -> [FilePath] -> DynamicEnv -> !Supply -> ModuleEnv
- Cryptol.ModuleSystem.Env: addLoadedModule :: ModulePath -> String -> Fingerprint -> Module -> LoadedModules -> LoadedModules
+ Cryptol.ModuleSystem.Env: addLoadedModule :: ModulePath -> String -> Fingerprint -> NamingEnv -> Module -> LoadedModules -> LoadedModules
- Cryptol.ModuleSystem.Exports: ExportSpec :: Set name -> Set name -> ExportSpec name
+ Cryptol.ModuleSystem.Exports: ExportSpec :: Map Namespace (Set name) -> ExportSpec name
- Cryptol.ModuleSystem.Exports: modExports :: Ord name => Module name -> ExportSpec name
+ Cryptol.ModuleSystem.Exports: modExports :: Ord name => ModuleG mname name -> ExportSpec name
- Cryptol.ModuleSystem.InstantiateModule: instantiateModule :: FreshM m => Module -> ModName -> Map TParam Type -> Map Name Expr -> m ([Located Prop], Module)
+ Cryptol.ModuleSystem.InstantiateModule: instantiateModule :: FreshM m => Module -> ModName -> Map TParam Type -> Map Name Expr -> m (Name -> Name, [Located Prop], Module)
- Cryptol.ModuleSystem.Interface: Iface :: !ModName -> IfaceDecls -> IfaceDecls -> IfaceParams -> Iface
+ Cryptol.ModuleSystem.Interface: Iface :: !mname -> IfaceDecls -> IfaceDecls -> IfaceParams -> IfaceG mname
- Cryptol.ModuleSystem.Interface: IfaceDecls :: Map Name IfaceTySyn -> Map Name IfaceNewtype -> Map Name IfaceAbstractType -> Map Name IfaceDecl -> IfaceDecls
+ Cryptol.ModuleSystem.Interface: IfaceDecls :: Map Name IfaceTySyn -> Map Name IfaceNewtype -> Map Name IfaceAbstractType -> Map Name IfaceDecl -> !Map Name (IfaceG Name) -> IfaceDecls
- Cryptol.ModuleSystem.Interface: [ifModName] :: Iface -> !ModName
+ Cryptol.ModuleSystem.Interface: [ifModName] :: IfaceG mname -> !mname
- Cryptol.ModuleSystem.Interface: [ifParams] :: Iface -> IfaceParams
+ Cryptol.ModuleSystem.Interface: [ifParams] :: IfaceG mname -> IfaceParams
- Cryptol.ModuleSystem.Interface: [ifPrivate] :: Iface -> IfaceDecls
+ Cryptol.ModuleSystem.Interface: [ifPrivate] :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem.Interface: [ifPublic] :: Iface -> IfaceDecls
+ Cryptol.ModuleSystem.Interface: [ifPublic] :: IfaceG mname -> IfaceDecls
- Cryptol.ModuleSystem.Monad: loadedModule :: ModulePath -> Fingerprint -> Module -> ModuleM ()
+ Cryptol.ModuleSystem.Monad: loadedModule :: ModulePath -> Fingerprint -> NamingEnv -> Module -> ModuleM ()
- Cryptol.ModuleSystem.Name: Declared :: !ModName -> !NameSource -> NameInfo
+ Cryptol.ModuleSystem.Name: Declared :: !ModPath -> !NameSource -> NameInfo
- Cryptol.ModuleSystem.Name: mkDeclared :: ModName -> NameSource -> Ident -> Maybe Fixity -> Range -> Supply -> (Name, Supply)
+ Cryptol.ModuleSystem.Name: mkDeclared :: Namespace -> ModPath -> NameSource -> Ident -> Maybe Fixity -> Range -> Supply -> (Name, Supply)
- Cryptol.ModuleSystem.Name: mkParameter :: Ident -> Range -> Supply -> (Name, Supply)
+ Cryptol.ModuleSystem.Name: mkParameter :: Namespace -> Ident -> Range -> Supply -> (Name, Supply)
- Cryptol.ModuleSystem.NamingEnv: InModule :: !ModName -> a -> InModule a
+ Cryptol.ModuleSystem.NamingEnv: InModule :: Maybe ModPath -> a -> InModule a
- Cryptol.ModuleSystem.NamingEnv: NamingEnv :: !Map PName [Name] -> !Map PName [Name] -> NamingEnv
+ Cryptol.ModuleSystem.NamingEnv: NamingEnv :: Map Namespace (Map PName [Name]) -> NamingEnv
- Cryptol.ModuleSystem.NamingEnv: newLocal :: FreshM m => PName -> Range -> m Name
+ Cryptol.ModuleSystem.NamingEnv: newLocal :: FreshM m => Namespace -> PName -> Range -> m Name
- Cryptol.ModuleSystem.NamingEnv: newTop :: FreshM m => ModName -> PName -> Maybe Fixity -> Range -> m Name
+ Cryptol.ModuleSystem.NamingEnv: newTop :: FreshM m => Namespace -> ModPath -> PName -> Maybe Fixity -> Range -> m Name
- Cryptol.ModuleSystem.NamingEnv: visibleNames :: NamingEnv -> (Set Name, Set Name)
+ Cryptol.ModuleSystem.NamingEnv: visibleNames :: NamingEnv -> Map Namespace (Set Name)
- Cryptol.ModuleSystem.Renamer: BoundReservedType :: PName -> Maybe Range -> Doc -> NameDisp -> RenamerError
+ Cryptol.ModuleSystem.Renamer: BoundReservedType :: PName -> Maybe Range -> Doc -> RenamerError
- Cryptol.ModuleSystem.Renamer: FixityError :: Located Name -> Fixity -> Located Name -> Fixity -> NameDisp -> RenamerError
+ Cryptol.ModuleSystem.Renamer: FixityError :: Located Name -> Fixity -> Located Name -> Fixity -> RenamerError
- Cryptol.ModuleSystem.Renamer: InModule :: !ModName -> a -> InModule a
+ Cryptol.ModuleSystem.Renamer: InModule :: Maybe ModPath -> a -> InModule a
- Cryptol.ModuleSystem.Renamer: InvalidConstraint :: Type PName -> NameDisp -> RenamerError
+ Cryptol.ModuleSystem.Renamer: InvalidConstraint :: Type PName -> RenamerError
- Cryptol.ModuleSystem.Renamer: MalformedBuiltin :: Type PName -> PName -> NameDisp -> RenamerError
+ Cryptol.ModuleSystem.Renamer: MalformedBuiltin :: Type PName -> PName -> RenamerError
- Cryptol.ModuleSystem.Renamer: MultipleSyms :: Located PName -> [Name] -> NameDisp -> RenamerError
+ Cryptol.ModuleSystem.Renamer: MultipleSyms :: Located PName -> [Name] -> RenamerError
- Cryptol.ModuleSystem.Renamer: OverlappingRecordUpdate :: Located [Selector] -> Located [Selector] -> NameDisp -> RenamerError
+ Cryptol.ModuleSystem.Renamer: OverlappingRecordUpdate :: Located [Selector] -> Located [Selector] -> RenamerError
- Cryptol.ModuleSystem.Renamer: OverlappingSyms :: [Name] -> NameDisp -> RenamerError
+ Cryptol.ModuleSystem.Renamer: OverlappingSyms :: [Name] -> RenamerError
- Cryptol.ModuleSystem.Renamer: SymbolShadowed :: Name -> [Name] -> NameDisp -> RenamerWarning
+ Cryptol.ModuleSystem.Renamer: SymbolShadowed :: PName -> Name -> [Name] -> RenamerWarning
- Cryptol.ModuleSystem.Renamer: UnusedName :: Name -> NameDisp -> RenamerWarning
+ Cryptol.ModuleSystem.Renamer: UnusedName :: Name -> RenamerWarning
- Cryptol.ModuleSystem.Renamer: renameModule :: Module PName -> RenameM (NamingEnv, Module Name)
+ Cryptol.ModuleSystem.Renamer: renameModule :: Module PName -> RenameM RenamedModule
- Cryptol.ModuleSystem.Renamer: renameType :: PName -> RenameM Name
+ Cryptol.ModuleSystem.Renamer: renameType :: NameType -> PName -> RenameM Name
- Cryptol.ModuleSystem.Renamer: renameVar :: PName -> RenameM Name
+ Cryptol.ModuleSystem.Renamer: renameVar :: NameType -> PName -> RenameM Name
- Cryptol.ModuleSystem.Renamer: runRenamer :: Supply -> ModName -> NamingEnv -> RenameM a -> (Either [RenamerError] (a, Supply), [RenamerWarning])
+ Cryptol.ModuleSystem.Renamer: runRenamer :: RenamerInfo -> RenameM a -> (Either [RenamerError] (a, Supply), [RenamerWarning])
- Cryptol.Parser.AST: Bind :: Located name -> [Pattern name] -> Located (BindDef name) -> Maybe (Schema name) -> Bool -> Maybe Fixity -> [Pragma] -> Bool -> Maybe Text -> Bind name
+ Cryptol.Parser.AST: Bind :: Located name -> [Pattern name] -> Located (BindDef name) -> Maybe (Schema name) -> Bool -> Maybe Fixity -> [Pragma] -> Bool -> Maybe Text -> !ExportType -> Bind name
- Cryptol.Parser.AST: Import :: !ModName -> Maybe ModName -> Maybe ImportSpec -> Import
+ Cryptol.Parser.AST: Import :: !mname -> Maybe ModName -> Maybe ImportSpec -> ImportG mname
- Cryptol.Parser.AST: LetInput :: Decl name -> ReplInput name
+ Cryptol.Parser.AST: LetInput :: [Decl name] -> ReplInput name
- Cryptol.Parser.AST: Module :: Located ModName -> !Maybe (Located ModName) -> [Located Import] -> [TopDecl name] -> Module name
+ Cryptol.Parser.AST: Module :: Located mname -> !Maybe (Located ModName) -> [TopDecl name] -> ModuleG mname name
- Cryptol.Parser.AST: [iAs] :: Import -> Maybe ModName
+ Cryptol.Parser.AST: [iAs] :: ImportG mname -> Maybe ModName
- Cryptol.Parser.AST: [iModule] :: Import -> !ModName
+ Cryptol.Parser.AST: [iModule] :: ImportG mname -> !mname
- Cryptol.Parser.AST: [iSpec] :: Import -> Maybe ImportSpec
+ Cryptol.Parser.AST: [iSpec] :: ImportG mname -> Maybe ImportSpec
- Cryptol.Parser.AST: [mDecls] :: Module name -> [TopDecl name]
+ Cryptol.Parser.AST: [mDecls] :: ModuleG mname name -> [TopDecl name]
- Cryptol.Parser.AST: [mInstance] :: Module name -> !Maybe (Located ModName)
+ Cryptol.Parser.AST: [mInstance] :: ModuleG mname name -> !Maybe (Located ModName)
- Cryptol.Parser.AST: [mName] :: Module name -> Located ModName
+ Cryptol.Parser.AST: [mName] :: ModuleG mname name -> Located mname
- Cryptol.Symbolic.What4: satProveOffline :: W4ProverConfig -> Bool -> Bool -> ProverCommand -> ((Handle -> IO ()) -> IO ()) -> ModuleCmd (Maybe String)
+ Cryptol.Symbolic.What4: satProveOffline :: Bool -> Bool -> ProverCommand -> ((Handle -> IO ()) -> IO ()) -> ModuleCmd (Maybe String)
- 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 -> SolverConfig -> [FilePath] -> !PrimMap -> !Supply -> Solver -> InferInput
+ 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: tcDecls :: FromDecl d => [d] -> InferInput -> IO (InferOutput [DeclGroup])
+ Cryptol.TypeCheck: tcDecls :: [TopDecl Name] -> InferInput -> IO (InferOutput ([DeclGroup], Map Name TySyn))
- Cryptol.TypeCheck: tcModuleInst :: Module -> Module Name -> InferInput -> IO (InferOutput Module)
+ Cryptol.TypeCheck: tcModuleInst :: IORef NamingEnv -> Module -> Module Name -> InferInput -> IO (InferOutput Module)
- Cryptol.TypeCheck.AST: ExportSpec :: Set name -> Set name -> ExportSpec name
+ Cryptol.TypeCheck.AST: ExportSpec :: Map Namespace (Set name) -> ExportSpec name
- Cryptol.TypeCheck.AST: Import :: !ModName -> Maybe ModName -> Maybe ImportSpec -> Import
+ Cryptol.TypeCheck.AST: Import :: !mname -> Maybe ModName -> Maybe ImportSpec -> ImportG mname
- Cryptol.TypeCheck.AST: Module :: !ModName -> ExportSpec Name -> [Import] -> Map Name TySyn -> Map Name Newtype -> Map Name AbstractType -> Map Name ModTParam -> [Located Prop] -> Map Name ModVParam -> [DeclGroup] -> Module
+ 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: [iAs] :: Import -> Maybe ModName
+ Cryptol.TypeCheck.AST: [iAs] :: ImportG mname -> Maybe ModName
- Cryptol.TypeCheck.AST: [iModule] :: Import -> !ModName
+ Cryptol.TypeCheck.AST: [iModule] :: ImportG mname -> !mname
- Cryptol.TypeCheck.AST: [iSpec] :: Import -> Maybe ImportSpec
+ Cryptol.TypeCheck.AST: [iSpec] :: ImportG mname -> Maybe ImportSpec
- Cryptol.TypeCheck.AST: [mDecls] :: Module -> [DeclGroup]
+ Cryptol.TypeCheck.AST: [mDecls] :: ModuleG mname -> [DeclGroup]
- Cryptol.TypeCheck.AST: [mExports] :: Module -> ExportSpec Name
+ Cryptol.TypeCheck.AST: [mExports] :: ModuleG mname -> ExportSpec Name
- Cryptol.TypeCheck.AST: [mImports] :: Module -> [Import]
+ Cryptol.TypeCheck.AST: [mImports] :: ModuleG mname -> [Import]
- Cryptol.TypeCheck.AST: [mName] :: Module -> !ModName
+ Cryptol.TypeCheck.AST: [mName] :: ModuleG mname -> !mname
- Cryptol.TypeCheck.AST: [mNewtypes] :: Module -> Map Name Newtype
+ Cryptol.TypeCheck.AST: [mNewtypes] :: ModuleG mname -> Map Name Newtype
- Cryptol.TypeCheck.AST: [mParamConstraints] :: Module -> [Located Prop]
+ Cryptol.TypeCheck.AST: [mParamConstraints] :: ModuleG mname -> [Located Prop]
- Cryptol.TypeCheck.AST: [mParamFuns] :: Module -> Map Name ModVParam
+ Cryptol.TypeCheck.AST: [mParamFuns] :: ModuleG mname -> Map Name ModVParam
- Cryptol.TypeCheck.AST: [mParamTypes] :: Module -> Map Name ModTParam
+ Cryptol.TypeCheck.AST: [mParamTypes] :: ModuleG mname -> Map Name ModTParam
- Cryptol.TypeCheck.AST: [mPrimTypes] :: Module -> Map Name AbstractType
+ Cryptol.TypeCheck.AST: [mPrimTypes] :: ModuleG mname -> Map Name AbstractType
- Cryptol.TypeCheck.AST: [mTySyns] :: Module -> Map Name TySyn
+ Cryptol.TypeCheck.AST: [mTySyns] :: ModuleG mname -> Map Name TySyn
- Cryptol.TypeCheck.AST: isParametrizedModule :: Module -> Bool
+ Cryptol.TypeCheck.AST: isParametrizedModule :: ModuleG mname -> Bool
- Cryptol.TypeCheck.CheckModuleInstance: checkModuleInstance :: Module -> Module -> InferM Module
+ Cryptol.TypeCheck.CheckModuleInstance: checkModuleInstance :: Module -> Module -> InferM (Name -> Name, Module)
- 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 -> SolverConfig -> [FilePath] -> !PrimMap -> !Supply -> Solver -> InferInput
+ 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: RO :: Range -> Map Name VarType -> [TParam] -> Map Name (DefLoc, TySyn) -> Map Name (DefLoc, Newtype) -> Map Name (DefLoc, AbstractType) -> Map Name ModTParam -> [Located Prop] -> Map Name ModVParam -> Map Int HasGoalSln -> Bool -> Bool -> Solver -> !PrimMap -> !IORef Int -> RO
+ Cryptol.TypeCheck.Monad: RO :: Range -> Map Name VarType -> [TParam] -> 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] -> !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: getAbstractTypes :: InferM (Map Name (DefLoc, AbstractType))
+ Cryptol.TypeCheck.Monad: getAbstractTypes :: InferM (Map Name AbstractType)
- Cryptol.TypeCheck.Monad: getNewtypes :: InferM (Map Name (DefLoc, Newtype))
+ Cryptol.TypeCheck.Monad: getNewtypes :: InferM (Map Name Newtype)
- Cryptol.TypeCheck.Monad: getTSyns :: InferM (Map Name (DefLoc, TySyn))
+ Cryptol.TypeCheck.Monad: getTSyns :: InferM (Map Name TySyn)
- Cryptol.TypeCheck.Monad: newParamName :: Ident -> InferM Name
+ Cryptol.TypeCheck.Monad: newParamName :: Namespace -> Ident -> InferM Name
- Cryptol.TypeCheck.Parseable: maybeNameDoc :: Maybe Name -> Doc
+ Cryptol.TypeCheck.Parseable: maybeNameDoc :: Maybe Name -> Doc Void
- Cryptol.TypeCheck.Parseable: showParseable :: ShowParseable t => t -> Doc
+ Cryptol.TypeCheck.Parseable: showParseable :: ShowParseable t => t -> Doc Void
- Cryptol.TypeCheck.Solver.SMT: startSolver :: SolverConfig -> IO Solver
+ Cryptol.TypeCheck.Solver.SMT: startSolver :: IO () -> SolverConfig -> IO Solver
- Cryptol.TypeCheck.Solver.SMT: withSolver :: SolverConfig -> (Solver -> IO a) -> IO a
+ Cryptol.TypeCheck.Solver.SMT: withSolver :: IO () -> SolverConfig -> (Solver -> IO a) -> IO a
- Cryptol.Utils.PP: Doc :: (NameDisp -> Doc) -> Doc
+ Cryptol.Utils.PP: Doc :: (NameDisp -> Doc Void) -> Doc
- Cryptol.Utils.PP: NameDisp :: (ModName -> Ident -> Maybe NameFormat) -> NameDisp
+ Cryptol.Utils.PP: NameDisp :: (OrigName -> Maybe NameFormat) -> NameDisp
- Cryptol.Utils.PP: PPOpts :: Bool -> Int -> Int -> Int -> PPFloatFormat -> PPOpts
+ Cryptol.Utils.PP: PPOpts :: Bool -> Int -> Int -> Int -> PPFloatFormat -> FieldOrder -> PPOpts
- Cryptol.Utils.PP: getNameFormat :: ModName -> Ident -> NameDisp -> NameFormat
+ Cryptol.Utils.PP: getNameFormat :: OrigName -> NameDisp -> NameFormat
- Cryptol.Utils.PP: infixl 6 <+>
+ Cryptol.Utils.PP: infixl 6 </>
- Cryptol.Utils.PP: liftSep :: ([Doc] -> Doc) -> [Doc] -> Doc
+ Cryptol.Utils.PP: liftSep :: ([Doc Void] -> Doc Void) -> [Doc] -> Doc
- Cryptol.Utils.PP: neverQualifyMod :: ModName -> NameDisp
+ Cryptol.Utils.PP: neverQualifyMod :: ModPath -> NameDisp
- Cryptol.Utils.PP: runDoc :: NameDisp -> Doc -> Doc
+ Cryptol.Utils.PP: runDoc :: NameDisp -> Doc -> Doc Void
Files
- CHANGES.md +78/−0
- cryptol.cabal +17/−9
- cryptol/Main.hs +4/−10
- cryptol/REPL/Haskeline.hs +2/−2
- lib/Array.cry +44/−0
- lib/Cryptol.cry +102/−24
- lib/CryptolTC.z3 +14/−8
- lib/SuiteB.cry +1/−1
- src/Cryptol/Backend.hs +88/−2
- src/Cryptol/Backend/Concrete.hs +30/−3
- src/Cryptol/Backend/Monad.hs +43/−8
- src/Cryptol/Backend/SBV.hs +12/−3
- src/Cryptol/Backend/SeqMap.hs +301/−0
- src/Cryptol/Backend/What4.hs +13/−6
- src/Cryptol/Backend/WordValue.hs +759/−0
- src/Cryptol/Eval.hs +33/−202
- src/Cryptol/Eval/Concrete.hs +56/−181
- src/Cryptol/Eval/Env.hs +0/−2
- src/Cryptol/Eval/Generic.hs +398/−583
- src/Cryptol/Eval/Reference.lhs +83/−25
- src/Cryptol/Eval/SBV.hs +59/−201
- src/Cryptol/Eval/Value.hs +123/−296
- src/Cryptol/Eval/What4.hs +62/−236
- src/Cryptol/F2.hs +2/−1
- src/Cryptol/ModuleSystem.hs +11/−4
- src/Cryptol/ModuleSystem/Base.hs +76/−67
- src/Cryptol/ModuleSystem/Env.hs +93/−101
- src/Cryptol/ModuleSystem/Exports.hs +48/−31
- src/Cryptol/ModuleSystem/InstantiateModule.hs +33/−14
- src/Cryptol/ModuleSystem/Interface.hs +80/−67
- src/Cryptol/ModuleSystem/Monad.hs +16/−19
- src/Cryptol/ModuleSystem/Name.hs +74/−66
- src/Cryptol/ModuleSystem/NamingEnv.hs +213/−135
- src/Cryptol/ModuleSystem/Renamer.hs +514/−485
- src/Cryptol/ModuleSystem/Renamer/Error.hs +205/−0
- src/Cryptol/ModuleSystem/Renamer/Monad.hs +342/−0
- src/Cryptol/Parser.y +84/−23
- src/Cryptol/Parser/AST.hs +158/−64
- src/Cryptol/Parser/Layout.hs +237/−0
- src/Cryptol/Parser/Lexer.x +16/−1
- src/Cryptol/Parser/LexerUtils.hs +6/−215
- src/Cryptol/Parser/Name.hs +2/−2
- src/Cryptol/Parser/Names.hs +22/−19
- src/Cryptol/Parser/NoInclude.hs +13/−7
- src/Cryptol/Parser/NoPat.hs +20/−2
- src/Cryptol/Parser/ParserUtils.hs +82/−24
- src/Cryptol/Parser/Position.hs +5/−3
- src/Cryptol/Parser/Selector.hs +5/−5
- src/Cryptol/Parser/Token.hs +119/−0
- src/Cryptol/REPL/Browse.hs +155/−0
- src/Cryptol/REPL/Command.hs +75/−263
- src/Cryptol/REPL/Monad.hs +150/−32
- src/Cryptol/Symbolic.hs +27/−5
- src/Cryptol/Symbolic/What4.hs +248/−79
- src/Cryptol/Testing/Random.hs +10/−8
- src/Cryptol/Transform/MonoValues.hs +5/−5
- src/Cryptol/Transform/Specialize.hs +3/−2
- src/Cryptol/TypeCheck.hs +47/−32
- src/Cryptol/TypeCheck/AST.hs +71/−66
- src/Cryptol/TypeCheck/CheckModuleInstance.hs +17/−4
- src/Cryptol/TypeCheck/Depends.hs +0/−214
- src/Cryptol/TypeCheck/Error.hs +64/−52
- src/Cryptol/TypeCheck/Infer.hs +177/−88
- src/Cryptol/TypeCheck/InferTypes.hs +38/−24
- src/Cryptol/TypeCheck/Interface.hs +73/−0
- src/Cryptol/TypeCheck/Monad.hs +222/−134
- src/Cryptol/TypeCheck/Parseable.hs +20/−8
- src/Cryptol/TypeCheck/SimpType.hs +13/−2
- src/Cryptol/TypeCheck/SimpleSolver.hs +1/−2
- src/Cryptol/TypeCheck/Solver/InfNat.hs +9/−10
- src/Cryptol/TypeCheck/Solver/Numeric/Fin.hs +2/−2
- src/Cryptol/TypeCheck/Solver/SMT.hs +23/−12
- src/Cryptol/TypeCheck/Solver/Selector.hs +6/−6
- src/Cryptol/TypeCheck/Subst.hs +8/−0
- src/Cryptol/TypeCheck/TCon.hs +3/−3
- src/Cryptol/TypeCheck/Type.hs +66/−29
- src/Cryptol/TypeCheck/TypeOf.hs +26/−3
- src/Cryptol/Utils/Ident.hs +82/−2
- src/Cryptol/Utils/PP.hs +134/−84
CHANGES.md view
@@ -1,3 +1,81 @@+# 2.12.0++## Language changes+* Updates to the layout rule. We simplified the specification and made+ some minor changes, in particular:+ - Paren blocks nested in a layout block need to respect the indentation+ if the layout block+ - We allow nested layout blocks to have the same indentation, which is+ convenient when writing `private` declarations as they don't need to+ be indented as long as they are at the end of the file.++* New enumeration forms `[x .. y by n]`, `[x .. <y by n]`,+ `[x .. y down by n]` and `[x .. >y down by n]` have been+ implemented. These new forms let the user explicitly specify+ the stride for an enumeration, as opposed to the previous+ `[x, y .. z]` form (where the stride was computed from `x` and `y`).++* Nested modules are now available (from pull request #1048). For example, the following is now valid Cryptol:++ module SubmodTest where++ import submodule B as C++ submodule A where+ propA = C::y > 5++ submodule B where+ y : Integer+ y = 42++## New features++* What4 prover backends now feature an improved multi-SAT procedure+ which is significantly faster than the old algorithm. Thanks to+ Levent Erkök for the suggestion.++* There is a new `w4-abc` solver option, which communicates to ABC+ as an external process via What4.++* Expanded support for declaration forms in the REPL. You can now+ define infix operators, type synonyms and mutually-recursive functions,+ and state signatures and fixity declarations. Multiple declarations+ can be combined into a single line by separating them with `;`,+ which is necessary for stating a signature together with a+ definition, etc.+ +* There is a new `:set path` REPL option that provides an alternative to+ `CRYPTOLPATH` for controlling where to search for imported modules+ (issue #631).++* The `cryptol-remote-api` server now natively supports HTTPS (issue+ #1008), `newtype` values (issue #1033), and safety checking (issue+ #1166).++* Releases optionally include solvers (issue #1111). See the+ `*-with-solvers*` files in the assets list for this release.++## Bug fixes++* Closed issues #422, #436, #619, #631, #633, #640, #680, #734, #735,+ #759, #760, #764, #849, #996, #1000, #1008, #1019, #1032, #1033,+ #1034, #1043, #1047, #1060, #1064, #1083, #1084, #1087, #1102, #1111,+ #1113, #1117, #1125, #1133, #1142, #1144, #1145, #1146, #1157, #1160,+ #1163, #1166, #1169, #1175, #1179, #1182, #1190, #1191, #1196, #1197,+ #1204, #1209, #1210, #1213, #1216, #1223, #1226, #1238, #1239, #1240,+ #1241, #1250, #1256, #1259, #1261, #1266, #1274, #1275, #1283, and+ #1291.++* Merged pull requests #1048, #1128, #1129, #1130, #1131, #1135, #1136,+ #1137, #1139, #1148, #1149, #1150, #1152, #1154, #1156, #1158, #1159,+ #1161, #1164, #1165, #1168, #1170, #1171, #1172, #1173, #1174, #1176,+ #1181, #1183, #1186, #1188, #1192, #1193, #1194, #1195, #1199, #1200,+ #1202, #1203, #1205, #1207, #1211, #1214, #1215, #1218, #1219, #1221,+ #1224, #1225, #1227, #1228, #1230, #1231, #1232, #1234, #1242, #1243,+ #1244, #1245, #1246, #1247, #1248, #1251, #1252, #1254, #1255, #1258,+ #1263, #1265, #1268, #1269, #1270, #1271, #1272, #1273, #1276, #1281,+ #1282, #1284, #1285, #1286, #1287, #1288, #1293, #1294, and #1295.+ # 2.11.0 ## Language changes
cryptol.cabal view
@@ -1,6 +1,6 @@ Cabal-version: 2.4 Name: cryptol-Version: 2.11.0+Version: 2.12.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@@ -25,7 +25,8 @@ source-repository this type: git location: https://github.com/GaloisInc/cryptol.git- tag: 2.11.0+ -- add a tag on release branches+ tag: 2.12.0 flag static@@ -61,11 +62,10 @@ monad-control >= 1.0, monadLib >= 3.7.2, parameterized-utils >= 2.0.2,- pretty >= 1.1,+ prettyprinter >= 1.7.0, process >= 1.2,- random >= 1.0.1,- sbv >= 8.6 && < 8.13,- simple-smt >= 0.7.1,+ sbv >= 8.6 && < 8.17,+ simple-smt >= 0.9.7, stm >= 2.4, strict, text >= 1.1,@@ -74,13 +74,15 @@ mtl >= 2.2.1, time >= 1.6.0.1, panic >= 0.3,- what4 >= 1.1 && < 1.2+ what4 >= 1.2 && < 1.3 Build-tool-depends: alex:alex, happy:happy hs-source-dirs: src Exposed-modules: Cryptol.Parser, Cryptol.Parser.Lexer,+ Cryptol.Parser.Token,+ Cryptol.Parser.Layout, Cryptol.Parser.AST, Cryptol.Parser.Position, Cryptol.Parser.Names,@@ -110,9 +112,11 @@ Cryptol.ModuleSystem.Monad, Cryptol.ModuleSystem.Name, Cryptol.ModuleSystem.NamingEnv,- Cryptol.ModuleSystem.Renamer, Cryptol.ModuleSystem.Exports, Cryptol.ModuleSystem.InstantiateModule,+ Cryptol.ModuleSystem.Renamer,+ Cryptol.ModuleSystem.Renamer.Monad,+ Cryptol.ModuleSystem.Renamer.Error, Cryptol.TypeCheck, Cryptol.TypeCheck.Type,@@ -125,12 +129,12 @@ Cryptol.TypeCheck.Infer, Cryptol.TypeCheck.CheckModuleInstance, Cryptol.TypeCheck.InferTypes,+ Cryptol.TypeCheck.Interface, Cryptol.TypeCheck.Error, Cryptol.TypeCheck.Kind, Cryptol.TypeCheck.Subst, Cryptol.TypeCheck.Instantiate, Cryptol.TypeCheck.Unify,- Cryptol.TypeCheck.Depends, Cryptol.TypeCheck.PP, Cryptol.TypeCheck.Solve, Cryptol.TypeCheck.Default,@@ -162,8 +166,10 @@ Cryptol.Backend.Concrete, Cryptol.Backend.FloatHelpers, Cryptol.Backend.Monad,+ Cryptol.Backend.SeqMap, Cryptol.Backend.SBV, Cryptol.Backend.What4,+ Cryptol.Backend.WordValue, Cryptol.Eval, Cryptol.Eval.Concrete,@@ -188,6 +194,7 @@ Cryptol.Symbolic.What4, Cryptol.REPL.Command,+ Cryptol.REPL.Browse, Cryptol.REPL.Monad, Cryptol.REPL.Trie @@ -224,6 +231,7 @@ , directory , filepath , haskeline >= 0.7 && < 0.9+ , exceptions , monad-control , text , transformers
cryptol/Main.hs view
@@ -15,7 +15,7 @@ import Cryptol.REPL.Command (loadCmd,loadPrelude,CommandExitCode(..)) import Cryptol.REPL.Monad (REPL,updateREPLTitle,setUpdateREPLTitle,- io,prependSearchPath,setSearchPath)+ io,prependSearchPath,setSearchPath,parseSearchPath) import qualified Cryptol.REPL.Monad as REPL import Cryptol.ModuleSystem.Env(ModulePath(..)) @@ -32,7 +32,7 @@ import System.Directory (getTemporaryDirectory, removeFile) import System.Environment (getArgs, getProgName, lookupEnv) import System.Exit (exitFailure,exitSuccess)-import System.FilePath (searchPathSeparator, splitSearchPath, takeDirectory)+import System.FilePath (searchPathSeparator, takeDirectory) import System.IO (hClose, hPutStr, openTempFile) @@ -256,14 +256,8 @@ mCryptolPath <- io $ lookupEnv "CRYPTOLPATH" case mCryptolPath of Nothing -> return ()- Just path | optCryptolPathOnly opts -> setSearchPath path'- | otherwise -> prependSearchPath path'-#if defined(mingw32_HOST_OS) || defined(__MINGW32__)- -- Windows paths search from end to beginning- where path' = reverse (splitSearchPath path)-#else- where path' = splitSearchPath path-#endif+ Just path | optCryptolPathOnly opts -> setSearchPath (parseSearchPath path)+ | otherwise -> prependSearchPath (parseSearchPath path) smoke <- REPL.smokeTest case smoke of [] -> return ()
cryptol/REPL/Haskeline.hs view
@@ -16,7 +16,7 @@ import Cryptol.REPL.Command import Cryptol.REPL.Monad import Cryptol.REPL.Trie-import Cryptol.Utils.PP+import Cryptol.Utils.PP hiding ((</>)) import Cryptol.Utils.Logger(stdoutLogger) import Cryptol.Utils.Ident(modNameToText, interactiveName) @@ -99,7 +99,7 @@ getInputLines = handleInterrupt (MTL.lift (handleCtrlC Interrupted)) . loop [] where loop ls prompt =- do mb <- getInputLine prompt+ do mb <- fmap (filter (/= '\r')) <$> getInputLine prompt let newPropmpt = map (\_ -> ' ') prompt case mb of Nothing -> return NoMoreLines
lib/Array.cry view
@@ -11,3 +11,47 @@ primitive arrayLookup : {a, b} (Array a b) -> a -> b primitive arrayUpdate : {a, b} (Array a b) -> a -> b -> (Array a b) +/**+ * Copy elements from the source array to the destination array.+ *+ * 'arrayCopy dest_arr dest_idx src_arr src_idx len' copies the+ * elements from 'src_arr' at indices '[src_idx ..< (src_idx + len)]' into+ * 'dest_arr' at indices '[dest_idx ..< (dest_idx + len)]'.+ *+ * The result is undefined if either 'dest_idx + len' or 'src_idx + len'+ * wraps around.+ */+primitive arrayCopy : {n, a} (Array [n] a) -> [n] -> (Array [n] a) -> [n] -> [n] -> (Array [n] a)+/**+ * Set elements of the given array.+ *+ * 'arraySet' arr idx val len' sets the elements of 'arr' at indices+ * '[idx ..< (idx + len)]' to 'val'.+ *+ * The result is undefined if 'idx + len' wraps around.+ */+primitive arraySet : {n, a} (Array [n] a) -> [n] -> a -> [n] -> (Array [n] a)+/**+ * Check whether the lhs array and rhs array are equal at a range of+ * indices.+ *+ * 'arrayRangeEq sym lhs_arr lhs_idx rhs_arr rhs_idx len' checks whether+ * the elements of 'lhs_arr' at indices '[lhs_idx ..< (lhs_idx + len)]' and+ * the elements of 'rhs_arr' at indices '[rhs_idx ..< (rhs_idx + len)]' are+ * equal.+ *+ * The result is undefined if either 'lhs_idx + len' or 'rhs_idx + len'+ * wraps around.+ */+primitive arrayRangeEqual : {n, a} (Array [n] a) -> [n] -> (Array [n] a) -> [n] -> [n] -> Bool++arrayRangeLookup : {a, b, n} (Integral a, fin n, LiteralLessThan n a) => (Array a b) -> a -> [n]b+arrayRangeLookup arr idx = res+ where+ res @ i = arrayLookup arr (idx + i)++arrayRangeUpdate : {a, b, n} (Integral a, fin n, LiteralLessThan n a) => (Array a b) -> a -> [n]b -> (Array a b)+arrayRangeUpdate arr idx vals = arrs ! 0+ where+ arrs = [arr] # [ arrayUpdate acc (idx + i) val | acc <- arrs | i <- [0 ..< n] | val <- vals ]+
lib/Cryptol.cry view
@@ -32,7 +32,7 @@ /** * 'Z n' is the type of integers, modulo 'n'. *- * The values of 'Z n' may be thought of as equivalance+ * The values of 'Z n' may be thought of as equivalence * classes of integers according to the equivalence * 'x ~ y' iff 'n' divides 'x - y'. 'Z n' naturally * forms a ring, but does not support integral division@@ -41,9 +41,9 @@ * However, you may use the 'fromZ' operation * to project values in 'Z n' into the integers if such operations * are required. This will compute the reduced representative- * of the equivalance class. In other words, 'fromZ' computes+ * of the equivalence class. In other words, 'fromZ' computes * the (unique) integer value 'i' where '0 <= i < n' and- * 'i' is in the given equivalance class.+ * 'i' is in the given equivalence class. * * If the modulus 'n' is prime, 'Z n' also * supports computing inverses and forms a field.@@ -131,13 +131,13 @@ /** Divide numeric types, rounding up. */ primitive type { m : #, n : # }- (fin m, fin n, n >= 1) =>+ (fin n, n >= 1) => m /^ n : # /** How much we need to add to make a proper multiple of the second argument. */ primitive type { m : #, n : # }- (fin m, fin n, n >= 1) =>+ (fin n, n >= 1) => m %^ n : # /** The length of an enumeration. */@@ -195,26 +195,76 @@ /** * A finite sequence counting up from 'first' to 'last'. *- * '[a..b]' is syntactic sugar for 'fromTo`{first=a,last=b}'.+ * '[x .. y]' is syntactic sugar for 'fromTo`{first=x,last=y}'. */-primitive fromTo : {first, last, a} (fin last, last >= first,- Literal first a, Literal last a) =>- [1 + (last - first)]a+primitive fromTo : {first, last, a}+ (fin last, last >= first, Literal last a) =>+ [1 + (last - first)]a /** * A possibly infinite sequence counting up from 'first' up to (but not including) 'bound'. *- * Note that if 'first' = 'bound' then the sequence will be empty.+ * '[ x ..< y ]' is syntactic sugar for 'fromToLessThan`{first=x,bound=y}'.+ *+ * Note that if 'first' = 'bound' then the sequence will be empty. If 'bound = inf'+ * then the sequence will be infinite, and will eventually wrap around for bounded types. */ primitive fromToLessThan :- {first, bound, a} (fin first, bound >= first, LiteralLessThan bound a) => [bound - first]a+ {first, bound, a} (fin first, bound >= first, LiteralLessThan bound a) =>+ [bound - first]a +/**+ * A finite sequence counting up from 'first' to 'last' by 'stride'.+ * Note that 'last' will only be an element of the enumeration if+ * 'stride' divides 'last - first' evenly.+ *+ * '[x .. y by n]' is syntactic sugar for 'fromToBy`{first=x,last=y,stride=n}'.+ */+primitive fromToBy : {first, last, stride, a}+ (fin last, fin stride, stride >= 1, last >= first, Literal last a) =>+ [1 + (last - first)/stride]a /**+ * A finite sequence counting from 'first' up to (but not including) 'bound'+ * by 'stride'. Note that if 'first = bound' then the sequence will+ * be empty. If 'bound = inf' then the sequence will be infinite, and will+ * eventually wrap around for bounded types.+ *+ * '[x ..< y by n]' is syntactic sugar for 'fromToByLessThan`{first=x,bound=y,stride=n}'.+ */+primitive fromToByLessThan : {first, bound, stride, a}+ (fin first, fin stride, stride >= 1, bound >= first, LiteralLessThan bound a) =>+ [(bound - first)/^stride]a++/**+ * A finite sequence counting from 'first' down to 'last' by 'stride'.+ * Note that 'last' will only be an element of the enumeration if+ * 'stride' divides 'first - last' evenly.+ *+ * '[x .. y down by n]' is syntactic sugar for 'fromToDownBy`{first=x,last=y,stride=n}'.+ */+primitive fromToDownBy : {first, last, stride, a}+ (fin first, fin stride, stride >= 1, first >= last, Literal first a) =>+ [1 + (first - last)/stride]a++/**+ * A finite sequence counting from 'first' down to (but not including)+ * 'bound' by 'stride'.+ *+ * '[x ..> y down by n]' is syntactic sugar for+ * 'fromToDownByGreaterThan`{first=x,bound=y,stride=n}'.+ *+ * Note that if 'first = bound' the sequence will be empty.+ */+primitive fromToDownByGreaterThan : {first, bound, stride, a}+ (fin first, fin stride, stride >= 1, first >= bound, Literal first a) =>+ [(first - bound)/^stride]a++/** * A finite arithmetic sequence starting with 'first' and 'next', * stopping when the values reach or would skip over 'last'. *- * '[a,b..c]' is syntactic sugar for 'fromThenTo`{first=a,next=b,last=c}'.+ * '[x,y..z]' is syntactic sugar for 'fromThenTo`{first=x,next=y,last=z}'. */ primitive fromThenTo : {first, next, last, a, len} ( fin first, fin next, fin last@@ -224,12 +274,12 @@ // Fractional Literals --------------------- -/** 'FLiteral m n r a' asserts that the type `a' contains the-fraction `m/n`. The flag `r` indicates if we should round (`r >= 1`)+/** 'FLiteral m n r a' asserts that the type 'a' contains the+fraction 'm/n'. The flag 'r' indicates if we should round ('r >= 1') or report an error if the number can't be represented exactly. */ primitive type FLiteral : # -> # -> # -> * -> Prop -/** A fractional literal corresponding to `m/n` */+/** A fractional literal corresponding to 'm/n' */ primitive fraction : { m, n, r, a } FLiteral m n r a => a @@ -387,7 +437,7 @@ /** * Value types that correspond to a field; that is,- * a ring also posessing multiplicative inverses for+ * a ring also possessing multiplicative inverses for * non-zero elements. * * Floating-point values are only approximately a field,@@ -684,7 +734,12 @@ */ primitive lg2 : {n} (fin n) => [n] -> [n] +/**+ * Convert a signed 2's complement bitvector to an integer.+ */+primitive toSignedInteger : {n} (fin n, n >= 1) => [n] -> Integer + // Rational specific operations ---------------------------------------------- /**@@ -717,8 +772,9 @@ * Splits a sequence into a pair of sequences. * 'splitAt z = (x, y)' iff 'x # y = z'. */-primitive splitAt : {front, back, a} (fin front) => [front + back]a- -> ([front]a, [back]a)+splitAt : {front, back, a} (fin front) => [front + back]a+ -> ([front]a, [back]a)+splitAt xs = (take`{front,back} xs, drop`{front,back} xs) /** * Concatenates a list of sequences.@@ -745,18 +801,15 @@ */ primitive transpose : {rows, cols, a} [rows][cols]a -> [cols][rows]a - /** * Select the first (left-most) 'front' elements of a sequence. */-take : {front, back, a} (fin front) => [front + back]a -> [front]a-take (x # _) = x+primitive take : {front, back, a} [front + back]a -> [front]a /** * Select all the elements after (to the right of) the 'front' elements of a sequence. */-drop : {front, back, a} (fin front) => [front + back]a -> [back]a-drop ((_ : [front] _) # y) = y+primitive drop : {front, back, a} (fin front) => [front + back]a -> [back]a /** * Drop the first (left-most) element of a sequence.@@ -899,6 +952,31 @@ generate f = [ f i | i <- [0 .. <n] ] +/**+ * Sort a sequence of elements. Equivalent to 'sortBy (<=)'.+ */+sort : {a, n} (Cmp a, fin n) => [n]a -> [n]a+sort = sortBy (<=)++/**+ * Sort a sequence according to the given less-than-or-equal relation.+ * The sorting is stable, so it preserves the relative position of any+ * pair of elements that are equivalent according to the order relation.+ */+sortBy : {a, n} (fin n) => (a -> a -> Bit) -> [n]a -> [n]a+sortBy le vs =+ if `n == (0 : Integer) then vs+ else drop`{1 - min 1 n} (insertBy (vs@0) (sortBy le (drop`{min 1 n} vs)))+ where+ insertBy : {k} (fin k) => a -> [k]a -> [k+1]a+ insertBy x0 ys = xys.0 # [last xs]+ where+ xs : [k+1]a+ xs = [x0] # xys.1+ xys : [k](a, a)+ xys = [ if le x y then (x, y) else (y, x) | x <- xs | y <- ys ]++ // GF_2^n polynomial computations ------------------------------------------- /**@@ -920,7 +998,7 @@ /** * Parallel map. The given function is applied to each element in the- * given finite seqeuence, and the results are computed in parallel.+ * given finite sequence, and the results are computed in parallel. * The values in the resulting sequence are reduced to normal form, * as is done with the deepseq operation. *
lib/CryptolTC.z3 view
@@ -267,10 +267,12 @@ )) ) -- (declare-fun cryExpUnknown (Int Int) Int) +(assert (forall ((x Int) (y Int))+ (=> (and (> y 0) (> x 0))+ (>= (cryExpUnknown x y) x))))+ (define-fun cryExpTable ((x Int) (y Int)) Int (ite (= y 0) 1 (ite (= y 1) x@@ -291,15 +293,19 @@ ) (define-fun cryCeilDiv ((x InfNat) (y InfNat)) InfNat- (ite (or (isErr x) (isErr y) (not (isFin x)) (not (isFin y))) cryErr- (ite (= (value y) 0) cryErr (cryNat (- (div (- (value x)) (value y)))))- )+ (ite (or (isErr x) (isErr y) (not (isFin y))) cryErr+ (ite (= (value y) 0) cryErr+ (ite (not (isFin x)) cryInf+ (cryNat (- (div (- (value x)) (value y))))+ ))) ) (define-fun cryCeilMod ((x InfNat) (y InfNat)) InfNat- (ite (or (isErr x) (isErr y) (not (isFin x)) (not (isFin y))) cryErr- (ite (= (value y) 0) cryErr (cryNat (mod (- (value x)) (value y))))- )+ (ite (or (isErr x) (isErr y) (not (isFin y))) cryErr+ (ite (= (value y) 0) cryErr+ (ite (not (isFin x)) (cryNat 0)+ (cryNat (mod (- (value x)) (value y)))+ ))) ) (define-fun cryLenFromThenTo ((x InfNat) (y InfNat) (z InfNat)) InfNat
lib/SuiteB.cry view
@@ -205,7 +205,7 @@ type sha2_padded_size w L = sha2_num_blocks w L * sha2_block_size w sha2pad : {w, L} (fin w, fin L, w >= 1) => [L] -> [sha2_padded_size w L]- sha2pad M = M # 0b1 # zero # ((fromInteger `L) : [2*w])+ sha2pad M = rnf (M # 0b1 # zero # ((fromInteger `L) : [2*w])) sha2blocks : {w, L} (fin w, fin L, w >= 1) => [L] -> [sha2_num_blocks w L][16][w]
src/Cryptol/Backend.hs view
@@ -7,7 +7,11 @@ , cryUserError , cryNoPrimError , FPArith2+ , IndexDirection(..) + , enumerateIntBits+ , enumerateIntBits'+ -- * Rationals , SRational(..) , intToRational@@ -29,15 +33,21 @@ , iteRational ) where +import qualified Control.Exception as X import Control.Monad.IO.Class import Data.Kind (Type) import Cryptol.Backend.FloatHelpers (BF) import Cryptol.Backend.Monad- ( EvalError(..), CallStack, pushCallFrame )+ ( EvalError(..), Unsupported(..), CallStack, pushCallFrame ) import Cryptol.ModuleSystem.Name(Name) import Cryptol.Parser.Position+import Cryptol.TypeCheck.Solver.InfNat(Nat'(..),widthInteger) +data IndexDirection+ = IndexForward+ | IndexBackward+ invalidIndex :: Backend sym => sym -> Integer -> SEval sym a invalidIndex sym i = raiseError sym (InvalidIndex (Just i)) @@ -191,6 +201,31 @@ iteRational sym p (SRational a b) (SRational c d) = SRational <$> iteInteger sym p a c <*> iteInteger sym p b d +-- | Compute the list of bits in an integer in big-endian order.+-- The integer argument is a concrete upper bound for+-- the symbolic integer.+enumerateIntBits' :: Backend sym =>+ sym ->+ Integer ->+ SInteger sym ->+ SEval sym (Integer, [SBit sym])+enumerateIntBits' sym n idx =+ do let width = widthInteger n+ w <- wordFromInt sym width idx+ bs <- unpackWord sym w+ pure (width, bs)++-- | Compute the list of bits in an integer in big-endian order.+-- Fails if neither the sequence length nor the type value+-- provide an upper bound for the integer.+enumerateIntBits :: Backend sym =>+ sym ->+ Nat' ->+ SInteger sym ->+ SEval sym (Integer, [SBit sym])+enumerateIntBits sym (Nat n) idx = enumerateIntBits' sym n idx+enumerateIntBits _sym Inf _ = liftIO (X.throw (UnsupportedSymbolicOp "unbounded integer shifting"))+ -- | This type class defines a collection of operations on bits, words and integers that -- are necessary to define generic evaluator primitives that operate on both concrete -- and symbolic values uniformly.@@ -205,7 +240,7 @@ -- | Check if an operation is "ready", which means its -- evaluation will be trivial.- isReady :: sym -> SEval sym a -> Bool+ isReady :: sym -> SEval sym a -> SEval sym (Maybe a) -- | Produce a thunk value which can be filled with its associated computation -- after the fact. A preallocated thunk is returned, along with an operation to@@ -488,6 +523,51 @@ SWord sym -> SEval sym (SWord sym) + -- | Shift a bitvector left by the specified amount.+ -- The shift amount is considered as an unsigned value.+ -- Shifting by more than the word length results in 0.+ wordShiftLeft ::+ sym ->+ SWord sym {- ^ value to shift -} ->+ SWord sym {- ^ amount to shift by -} ->+ SEval sym (SWord sym)++ -- | Shift a bitvector right by the specified amount.+ -- This is a logical shift, which shifts in 0 values+ -- on the left. The shift amount is considered as an+ -- unsigned value. Shifting by more than the word length+ -- results in 0.+ wordShiftRight ::+ sym ->+ SWord sym {- ^ value to shift -} ->+ SWord sym {- ^ amount to shift by -} ->+ SEval sym (SWord sym)++ -- | Shift a bitvector right by the specified amount. This is an+ -- arithmetic shift, which shifts in copies of the high bit on the+ -- left. The shift amount is considered as an unsigned+ -- value. Shifting by more than the word length results in filling+ -- the bitvector with the high bit.+ wordSignedShiftRight ::+ sym ->+ SWord sym {- ^ value to shift -} ->+ SWord sym {- ^ amount to shift by -} ->+ SEval sym (SWord sym)++ wordRotateLeft ::+ sym ->+ SWord sym {- ^ value to rotate -} ->+ SWord sym {- ^ amount to rotate by -} ->+ SEval sym (SWord sym)++ wordRotateRight ::+ sym ->+ SWord sym {- ^ value to rotate -} ->+ SWord sym {- ^ amount to rotate by -} ->+ SEval sym (SWord sym)+++ -- | 2's complement negation of bitvectors wordNegate :: sym ->@@ -530,6 +610,12 @@ -- | Construct an integer value from the given packed word. wordToInt ::+ sym ->+ SWord sym ->+ SEval sym (SInteger sym)++ -- | Construct a signed integer value from the given packed word.+ wordToSignedInt :: sym -> SWord sym -> SEval sym (SInteger sym)
src/Cryptol/Backend/Concrete.hs view
@@ -114,7 +114,7 @@ prefix = case base of 2 -> text "0b" <.> padding 1 8 -> text "0o" <.> padding 3- 10 -> empty+ 10 -> mempty 16 -> text "0x" <.> padding 4 _ -> text "0" <.> char '<' <.> int base <.> char '>' @@ -152,8 +152,7 @@ wordUpdate _ (BV w x) idx True = pure $! BV w (setBit x (fromInteger (w - 1 - idx))) wordUpdate _ (BV w x) idx False = pure $! BV w (clearBit x (fromInteger (w - 1 - idx))) - isReady _ (Ready _) = True- isReady _ _ = False+ isReady _ = maybeReady mergeEval _sym f c mx my = do x <- mx@@ -186,6 +185,7 @@ integerAsLit _ = Just wordToInt _ (BV _ x) = pure x+ wordToSignedInt _ (BV w x) = pure $! signedValue w x wordFromInt _ w x = pure $! mkBv w x packWord _ bits = pure $! BV (toInteger w) a@@ -284,6 +284,33 @@ sy = signedValue i y pure $! mkBv i (sx `rem` sy) | otherwise = panic "Attempt to mod words of different sizes: wordSignedMod" [show i, show j]++ wordShiftLeft _sym (BV w ival) (BV _ by)+ | by >= w = pure $! BV w 0+ | by > toInteger (maxBound :: Int) = panic "shl" ["Shift amount too large", show by]+ | otherwise = pure $! mkBv w (shiftL ival (fromInteger by))++ wordShiftRight _sym (BV w ival) (BV _ by)+ | by >= w = pure $! BV w 0+ | by > toInteger (maxBound :: Int) = panic "lshr" ["Shift amount too large", show by]+ | otherwise = pure $! BV w (shiftR ival (fromInteger by))++ wordSignedShiftRight _sym (BV w ival) (BV _ by) =+ let by' = min w by in+ if by' > toInteger (maxBound :: Int) then+ panic "wordSignedShiftRight" ["Shift amount too large", show by]+ else+ pure $! mkBv w (shiftR (signedValue w ival) (fromInteger by'))++ wordRotateRight _sym (BV 0 i) _ = pure (BV 0 i)+ wordRotateRight _sym (BV w i) (BV _ by) =+ pure . mkBv w $! (i `shiftR` b) .|. (i `shiftL` (fromInteger w - b))+ where b = fromInteger (by `mod` w)++ wordRotateLeft _sym (BV 0 i) _ = pure (BV 0 i)+ wordRotateLeft _sym (BV w i) (BV _ by) =+ pure . mkBv w $! (i `shiftL` b) .|. (i `shiftR` (fromInteger w - b))+ where b = fromInteger (by `mod` w) wordLg2 _ (BV i x) = pure $! mkBv i (lg2 x)
src/Cryptol/Backend/Monad.hs view
@@ -63,12 +63,33 @@ -- | The type of dynamic call stacks for the interpreter. -- New frames are pushed onto the right side of the sequence.-type CallStack = Seq (Name, Range)+data CallStack+ = EmptyCallStack+ | CombineCallStacks !CallStack !CallStack+ | PushCallFrame !Name !Range !CallStack +instance Semigroup CallStack where+ (<>) = CombineCallStacks++instance Monoid CallStack where+ mempty = EmptyCallStack++type CallStack' = Seq (Name, Range)++evalCallStack :: CallStack -> CallStack'+evalCallStack stk =+ case stk of+ EmptyCallStack -> mempty+ CombineCallStacks appstk fnstk -> combineCallStacks' (evalCallStack appstk) (evalCallStack fnstk)+ PushCallFrame n r stk1 -> pushCallFrame' n r (evalCallStack stk1)+ -- | Pretty print a call stack with each call frame on a separate -- line, with most recent call frames at the top. displayCallStack :: CallStack -> Doc-displayCallStack = vcat . map f . toList . Seq.reverse+displayCallStack = displayCallStack' . evalCallStack++displayCallStack' :: CallStack' -> Doc+displayCallStack' = vcat . map f . toList . Seq.reverse where f (nm,rng) | rng == emptyRange = pp nm@@ -92,7 +113,15 @@ CallStack {- ^ call stack of the application context -} -> CallStack {- ^ call stack of the function being applied -} -> CallStack-combineCallStacks appstk fnstk = appstk <> dropCommonPrefix appstk fnstk+combineCallStacks appstk EmptyCallStack = appstk+combineCallStacks EmptyCallStack fnstk = fnstk+combineCallStacks appstk fnstk = CombineCallStacks appstk fnstk++combineCallStacks' ::+ CallStack' {- ^ call stack of the application context -} ->+ CallStack' {- ^ call stack of the function being applied -} ->+ CallStack'+combineCallStacks' appstk fnstk = appstk <> dropCommonPrefix appstk fnstk where dropCommonPrefix _ Seq.Empty = Seq.Empty dropCommonPrefix Seq.Empty fs = fs@@ -102,9 +131,12 @@ -- | Add a call frame to the top of a call stack pushCallFrame :: Name -> Range -> CallStack -> CallStack-pushCallFrame nm rng stk@( _ Seq.:|> (nm',rng'))+pushCallFrame nm rng stk = PushCallFrame nm rng stk++pushCallFrame' :: Name -> Range -> CallStack' -> CallStack'+pushCallFrame' nm rng stk@( _ Seq.:|> (nm',rng')) | nm == nm', rng == rng' = stk-pushCallFrame nm rng stk = stk Seq.:|> (nm,rng)+pushCallFrame' nm rng stk = stk Seq.:|> (nm,rng) -- | The monad for Cryptol evaluation.@@ -328,13 +360,15 @@ Eval $ \stk -> do let stk' = f stk -- putStrLn $ unwords ["Pushing call stack", show (displayCallStack stk')]- runEval stk' m+ seq stk' (runEval stk' m)+{-# INLINE modifyCallStack #-} -- | Execute the given evaluation action. runEval :: CallStack -> Eval a -> IO a runEval _ (Ready a) = return a runEval stk (Eval x) = x stk runEval _ (Thunk tv) = unDelay tv+{-# INLINE runEval #-} {-# INLINE evalBind #-} evalBind :: Eval a -> (a -> Eval b) -> Eval b@@ -415,11 +449,12 @@ deriving Typeable instance PP EvalErrorEx where- ppPrec _ (EvalErrorEx stk ex) = vcat ([ pp ex ] ++ callStk)+ ppPrec _ (EvalErrorEx stk0 ex) = vcat ([ pp ex ] ++ callStk) where+ stk = evalCallStack stk0 callStk | Seq.null stk = []- | otherwise = [ text "-- Backtrace --", displayCallStack stk ]+ | otherwise = [ text "-- Backtrace --", displayCallStack' stk ] instance Show EvalErrorEx where show = show . pp
src/Cryptol/Backend/SBV.hs view
@@ -48,7 +48,7 @@ import Cryptol.Backend.Monad ( Eval(..), blackhole, delayFill, evalSpark , EvalError(..), EvalErrorEx(..), Unsupported(..)- , modifyCallStack, getCallStack+ , modifyCallStack, getCallStack, maybeReady ) import Cryptol.Utils.Panic (panic)@@ -162,8 +162,10 @@ | Just False <- svAsBool cond = raiseError sym err | otherwise = SBVEval (pure (SBVResult cond ())) - isReady _ (SBVEval (Ready _)) = True- isReady _ _ = False+ isReady _ (SBVEval m) = SBVEval $+ maybeReady m >>= \case+ Just x -> pure (Just <$> x)+ Nothing -> pure (pure Nothing) sDelayFill _ m retry msg = SBVEval $ do m' <- delayFill (sbvEval m) (sbvEval <$> retry) msg@@ -262,6 +264,12 @@ wordMult _ a b = pure $! svTimes a b wordNegate _ a = pure $! svUNeg a + wordShiftLeft _ a b = pure $! shl a b+ wordShiftRight _ a b = pure $! lshr a b+ wordRotateLeft _ a b = pure $! SBV.svRotateLeft a b+ wordRotateRight _ a b = pure $! SBV.svRotateRight a b+ wordSignedShiftRight _ a b = pure $! ashr a b+ wordDiv sym a b = do let z = literalSWord (intSizeOf b) 0 assertSideCondition sym (svNot (svEqual b z)) DivideByZero@@ -285,6 +293,7 @@ wordLg2 _ a = sLg2 a wordToInt _ x = pure $! svToInteger x+ wordToSignedInt _ x = pure $! svToInteger (svSign x) wordFromInt _ w i = pure $! svFromInteger w i intEq _ a b = pure $! svEqual a b
+ src/Cryptol/Backend/SeqMap.hs view
@@ -0,0 +1,301 @@+-- |+-- Module : Cryptol.Backend.SeqMap+-- Copyright : (c) 2013-2021 Galois, Inc.+-- License : BSD3+-- Maintainer : cryptol@galois.com+-- Stability : provisional+-- Portability : portable++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DoAndIfThenElse #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}++module Cryptol.Backend.SeqMap+ ( -- * Sequence Maps+ SeqMap+ , indexSeqMap+ , lookupSeqMap+ , finiteSeqMap+ , infiniteSeqMap+ , enumerateSeqMap+ , streamSeqMap+ , reverseSeqMap+ , updateSeqMap+ , dropSeqMap+ , concatSeqMap+ , splitSeqMap+ , memoMap+ , delaySeqMap+ , zipSeqMap+ , mapSeqMap+ , mergeSeqMap+ , barrelShifter+ , shiftSeqByInteger++ , IndexSegment(..)+ ) where++import qualified Control.Exception as X+import Control.Monad+import Control.Monad.IO.Class+import Data.Bits+import Data.List+import Data.IORef+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map++import Cryptol.Backend+import Cryptol.Backend.Concrete (Concrete)+import Cryptol.Backend.Monad (Unsupported(..))++import Cryptol.TypeCheck.Solver.InfNat(Nat'(..))+import Cryptol.Utils.Panic++-- | A sequence map represents a mapping from nonnegative integer indices+-- to values. These are used to represent both finite and infinite sequences.+data SeqMap sym a+ = IndexSeqMap !(Integer -> SEval sym a)+ | UpdateSeqMap !(Map Integer (SEval sym a))+ !(SeqMap sym a)+ | MemoSeqMap+ !Nat'+ !(IORef (Map Integer a))+ !(IORef (Integer -> SEval sym a))++indexSeqMap :: (Integer -> SEval sym a) -> SeqMap sym a+indexSeqMap = IndexSeqMap++lookupSeqMap :: Backend sym => SeqMap sym a -> Integer -> SEval sym a+lookupSeqMap (IndexSeqMap f) i = f i+lookupSeqMap (UpdateSeqMap m xs) i =+ case Map.lookup i m of+ Just x -> x+ Nothing -> lookupSeqMap xs i+lookupSeqMap (MemoSeqMap sz cache eval) i =+ do mz <- liftIO (Map.lookup i <$> readIORef cache)+ case mz of+ Just z -> return z+ Nothing ->+ do f <- liftIO (readIORef eval)+ v <- f i+ msz <- liftIO $ atomicModifyIORef' cache (\m ->+ let m' = Map.insert i v m in (m', Map.size m'))+ -- If we memoize the entire map, overwrite the evaluation closure to let+ -- the garbage collector reap it+ when (case sz of Inf -> False; Nat sz' -> toInteger msz >= sz')+ (liftIO (writeIORef eval+ (\j -> panic "lookupSeqMap" ["Messed up size accounting", show sz, show j])))+ return v++instance Backend sym => Functor (SeqMap sym) where+ fmap f xs = IndexSeqMap (\i -> f <$> lookupSeqMap xs i)++-- | Generate a finite sequence map from a list of values+finiteSeqMap :: Backend sym => sym -> [SEval sym a] -> SeqMap sym a+finiteSeqMap sym xs =+ UpdateSeqMap+ (Map.fromList (zip [0..] xs))+ (IndexSeqMap (\i -> invalidIndex sym i))++-- | Generate an infinite sequence map from a stream of values+infiniteSeqMap :: Backend sym => sym -> [SEval sym a] -> SEval sym (SeqMap sym a)+infiniteSeqMap sym xs =+ -- TODO: use an int-trie?+ memoMap sym Inf (IndexSeqMap $ \i -> genericIndex xs i)++-- | Create a finite list of length @n@ of the values from @[0..n-1]@ in+-- the given the sequence emap.+enumerateSeqMap :: (Backend sym, Integral n) => n -> SeqMap sym a -> [SEval sym a]+enumerateSeqMap n m = [ lookupSeqMap m i | i <- [0 .. (toInteger n)-1] ]++-- | Create an infinite stream of all the values in a sequence map+streamSeqMap :: Backend sym => SeqMap sym a -> [SEval sym a]+streamSeqMap m = [ lookupSeqMap m i | i <- [0..] ]++-- | Reverse the order of a finite sequence map+reverseSeqMap :: Backend sym =>+ Integer {- ^ Size of the sequence map -} ->+ SeqMap sym a ->+ SeqMap sym a+reverseSeqMap n vals = IndexSeqMap $ \i -> lookupSeqMap vals (n - 1 - i)++updateSeqMap :: SeqMap sym a -> Integer -> SEval sym a -> SeqMap sym a+updateSeqMap (UpdateSeqMap m sm) i x = UpdateSeqMap (Map.insert i x m) sm+updateSeqMap xs i x = UpdateSeqMap (Map.singleton i x) xs++-- | Concatenate the first @n@ values of the first sequence map onto the+-- beginning of the second sequence map.+concatSeqMap :: Backend sym => Integer -> SeqMap sym a -> SeqMap sym a -> SeqMap sym a+concatSeqMap n x y =+ IndexSeqMap $ \i ->+ if i < n+ then lookupSeqMap x i+ else lookupSeqMap y (i-n)++-- | Given a number @n@ and a sequence map, return two new sequence maps:+-- the first containing the values from @[0..n-1]@ and the next containing+-- the values from @n@ onward.+splitSeqMap :: Backend sym => Integer -> SeqMap sym a -> (SeqMap sym a, SeqMap sym a)+splitSeqMap n xs = (hd,tl)+ where+ hd = xs+ tl = IndexSeqMap $ \i -> lookupSeqMap xs (i+n)++-- | Drop the first @n@ elements of the given 'SeqMap'.+dropSeqMap :: Backend sym => Integer -> SeqMap sym a -> SeqMap sym a+dropSeqMap 0 xs = xs+dropSeqMap n xs = IndexSeqMap $ \i -> lookupSeqMap xs (i+n)++delaySeqMap :: Backend sym => sym -> SEval sym (SeqMap sym a) -> SEval sym (SeqMap sym a)+delaySeqMap sym xs =+ do xs' <- sDelay sym xs+ pure $ IndexSeqMap $ \i -> do m <- xs'; lookupSeqMap m i++-- | Given a sequence map, return a new sequence map that is memoized using+-- a finite map memo table.+memoMap :: Backend sym => sym -> Nat' -> SeqMap sym a -> SEval sym (SeqMap sym a)++-- Sequence is alreay memoized, just return it+memoMap _sym _sz x@(MemoSeqMap{}) = pure x++memoMap sym sz x = do+ stk <- sGetCallStack sym+ cache <- liftIO $ newIORef $ Map.empty+ evalRef <- liftIO $ newIORef $ eval stk+ return (MemoSeqMap sz cache evalRef)++ where+ eval stk i = sWithCallStack sym stk (lookupSeqMap x i)+++-- | Apply the given evaluation function pointwise to the two given+-- sequence maps.+zipSeqMap ::+ Backend sym =>+ sym ->+ (a -> a -> SEval sym a) ->+ Nat' ->+ SeqMap sym a ->+ SeqMap sym a ->+ SEval sym (SeqMap sym a)+zipSeqMap sym f sz x y =+ memoMap sym sz (IndexSeqMap $ \i -> join (f <$> lookupSeqMap x i <*> lookupSeqMap y i))++-- | Apply the given function to each value in the given sequence map+mapSeqMap ::+ Backend sym =>+ sym ->+ (a -> SEval sym a) ->+ Nat' ->+ SeqMap sym a ->+ SEval sym (SeqMap sym a)+mapSeqMap sym f sz x =+ memoMap sym sz (IndexSeqMap $ \i -> f =<< lookupSeqMap x i)+++{-# INLINE mergeSeqMap #-}+mergeSeqMap :: Backend sym =>+ sym ->+ (SBit sym -> a -> a -> SEval sym a) ->+ SBit sym ->+ SeqMap sym a ->+ SeqMap sym a ->+ SeqMap sym a+mergeSeqMap sym f c x y =+ IndexSeqMap $ \i -> mergeEval sym f c (lookupSeqMap x i) (lookupSeqMap y i)+++{-# INLINE shiftSeqByInteger #-}+shiftSeqByInteger :: Backend sym =>+ sym ->+ (SBit sym -> a -> a -> SEval sym a)+ {- ^ if/then/else operation of values -} ->+ (Integer -> Integer -> Maybe Integer)+ {- ^ reindexing operation -} ->+ SEval sym a {- ^ zero value -} ->+ Nat' {- ^ size of the sequence -} ->+ SeqMap sym a {- ^ sequence to shift -} ->+ SInteger sym {- ^ shift amount, assumed to be in range [0,len] -} ->+ SEval sym (SeqMap sym a)+shiftSeqByInteger sym merge reindex zro m xs idx+ | Just j <- integerAsLit sym idx = shiftOp xs j+ | otherwise =+ do (n, idx_bits) <- enumerateIntBits sym m idx+ barrelShifter sym merge shiftOp m xs n (map BitIndexSegment idx_bits)+ where+ shiftOp vs shft =+ pure $ indexSeqMap $ \i ->+ case reindex i shft of+ Nothing -> zro+ Just i' -> lookupSeqMap vs i'+++data IndexSegment sym+ = BitIndexSegment (SBit sym)+ | WordIndexSegment (SWord sym)++{-# SPECIALIZE+ barrelShifter ::+ Concrete ->+ (SBit Concrete -> a -> a -> SEval Concrete a) ->+ (SeqMap Concrete a -> Integer -> SEval Concrete (SeqMap Concrete a)) ->+ Nat' ->+ SeqMap Concrete a ->+ Integer ->+ [IndexSegment Concrete] ->+ SEval Concrete (SeqMap Concrete a)+ #-}+barrelShifter :: Backend sym =>+ sym ->+ (SBit sym -> a -> a -> SEval sym a)+ {- ^ if/then/else operation of values -} ->+ (SeqMap sym a -> Integer -> SEval sym (SeqMap sym a))+ {- ^ concrete shifting operation -} ->+ Nat' {- ^ Size of the map being shifted -} ->+ SeqMap sym a {- ^ initial value -} ->+ Integer {- Number of bits in shift amount -} ->+ [IndexSegment sym] {- ^ segments of the shift amount, in big-endian order -} ->+ SEval sym (SeqMap sym a)+barrelShifter sym mux shift_op sz x0 n0 bs0+ | n0 >= toInteger (maxBound :: Int) =+ liftIO (X.throw (UnsupportedSymbolicOp ("Barrel shifter with too many bits in shift amount: " ++ show n0)))+ | otherwise = go x0 (fromInteger n0) bs0++ where+ go x !_n [] = return x++ go x !n (WordIndexSegment w:bs) =+ let n' = n - fromInteger (wordLen sym w) in+ case wordAsLit sym w of+ Just (_,0) -> go x n' bs+ Just (_,j) ->+ do x_shft <- shift_op x (j * bit n')+ go x_shft n' bs+ Nothing ->+ do wbs <- unpackWord sym w+ go x n (map BitIndexSegment wbs ++ bs)++ go x !n (BitIndexSegment b:bs) =+ let n' = n - 1 in+ case bitAsLit sym b of+ Just False -> go x n' bs+ Just True ->+ do x_shft <- shift_op x (bit n')+ go x_shft n' bs+ Nothing ->+ do x_shft <- shift_op x (bit n')+ x' <- memoMap sym sz (mergeSeqMap sym mux b x_shft x)+ go x' n' bs
src/Cryptol/Backend/What4.hs view
@@ -39,7 +39,7 @@ import Cryptol.Backend.Monad ( Eval(..), EvalError(..), EvalErrorEx(..) , Unsupported(..), delayFill, blackhole, evalSpark- , modifyCallStack, getCallStack+ , modifyCallStack, getCallStack, maybeReady ) import Cryptol.Utils.Panic @@ -76,7 +76,7 @@ | W4Result !(W4.Pred sym) !a -- ^ safety predicate and result: the result only makes sense when -- the predicate holds.-+ deriving Functor -------------------------------------------------------------------------------- -- Moving between the layers@@ -215,10 +215,10 @@ | Just False <- W4.asConstantPred cond = evalError err | otherwise = addSafety cond - isReady sym m =- case w4Eval m (w4 sym) of- Ready _ -> True- _ -> False+ isReady sym m = W4Eval $ W4Conn $ \_ ->+ maybeReady (w4Eval m (w4 sym)) >>= \case+ Just x -> pure (Just <$> x)+ Nothing -> pure (W4Result (W4.backendPred (w4 sym) True) Nothing) sDelayFill _ m retry msg = total@@ -342,6 +342,12 @@ wordNegate sym x = liftIO (SW.bvNeg (w4 sym) x) wordLg2 sym x = sLg2 (w4 sym) x + wordShiftLeft sym x y = w4bvShl (w4 sym) x y+ wordShiftRight sym x y = w4bvLshr (w4 sym) x y+ wordRotateLeft sym x y = w4bvRol (w4 sym) x y+ wordRotateRight sym x y = w4bvRor (w4 sym) x y+ wordSignedShiftRight sym x y = w4bvAshr (w4 sym) x y+ wordDiv sym x y = do assertBVDivisor sym y liftIO (SW.bvUDiv (w4 sym) x y)@@ -356,6 +362,7 @@ liftIO (SW.bvSRem (w4 sym) x y) wordToInt sym x = liftIO (SW.bvToInteger (w4 sym) x)+ wordToSignedInt sym x = liftIO (SW.sbvToInteger (w4 sym) x) wordFromInt sym width i = liftIO (SW.integerToBV (w4 sym) i width) intPlus sym x y = liftIO $ W4.intAdd (w4 sym) x y
+ src/Cryptol/Backend/WordValue.hs view
@@ -0,0 +1,759 @@+-- |+-- Module : Cryptol.Backend.WordValue+-- Copyright : (c) 2013-2021 Galois, Inc.+-- License : BSD3+-- Maintainer : cryptol@galois.com+-- Stability : provisional+-- Portability : portable++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DoAndIfThenElse #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}++module Cryptol.Backend.WordValue+ ( -- * WordValue+ WordValue+ , wordVal+ , bitmapWordVal+ , asWordList+ , asWordVal+ , asBitsMap+ , joinWordVal+ , takeWordVal+ , dropWordVal+ , extractWordVal+ , wordValLogicOp+ , wordValUnaryOp+ , assertWordValueInBounds+ , enumerateWordValue+ , enumerateWordValueRev+ , enumerateIndexSegments+ , wordValueSize+ , indexWordValue+ , updateWordValue+ , delayWordValue+ , joinWords+ , shiftSeqByWord+ , shiftWordByInteger+ , shiftWordByWord+ , wordValAsLit+ , reverseWordVal+ , forceWordValue+ , wordValueEqualsInteger+ , updateWordByWord++ , mergeWord+ , mergeWord'+ ) where++import Control.Monad (unless)+import Data.Bits+import GHC.Generics (Generic)++import Cryptol.Backend+import Cryptol.Backend.Concrete (Concrete(..))+import Cryptol.Backend.Monad (EvalError(..))+import Cryptol.Backend.SeqMap++import Cryptol.TypeCheck.Solver.InfNat(widthInteger, Nat'(..))++-- | Force the evaluation of a word value+forceWordValue :: Backend sym => WordValue sym -> SEval sym ()+forceWordValue (WordVal w) = seq w (return ())+forceWordValue (ThunkWordVal _ m) = forceWordValue =<< m+forceWordValue (BitmapVal _n packed _) = do w <- packed; seq w (return ())++-- | An arbitrarily-chosen number of elements where we switch from a dense+-- sequence representation of bit-level words to 'SeqMap' representation.+largeBitSize :: Integer+largeBitSize = bit 32++-- | For efficiency reasons, we handle finite sequences of bits as special cases+-- in the evaluator. In cases where we know it is safe to do so, we prefer to+-- used a "packed word" representation of bit sequences. This allows us to rely+-- directly on Integer types (in the concrete evaluator) and SBV's Word types (in+-- the symbolic simulator).+--+-- However, if we cannot be sure all the bits of the sequence+-- will eventually be forced, we must instead rely on an explicit sequence of bits+-- representation.+data WordValue sym+ = ThunkWordVal Integer !(SEval sym (WordValue sym))+ | WordVal !(SWord sym) -- ^ Packed word representation for bit sequences.+ | BitmapVal+ !Integer -- ^ Length of the word+ !(SEval sym (SWord sym)) -- ^ Thunk for packing the word+ !(SeqMap sym (SBit sym)) -- ^+ deriving (Generic)++wordVal :: SWord sym -> WordValue sym+wordVal = WordVal++packBitmap :: Backend sym => sym -> Integer -> SeqMap sym (SBit sym) -> SEval sym (SWord sym)+packBitmap sym sz bs = packWord sym =<< sequence (enumerateSeqMap sz bs)++unpackBitmap :: Backend sym => sym -> SWord sym -> SeqMap sym (SBit sym)+unpackBitmap sym w = indexSeqMap $ \i -> wordBit sym w i++bitmapWordVal :: Backend sym => sym -> Integer -> SeqMap sym (SBit sym) -> SEval sym (WordValue sym)+bitmapWordVal sym sz bs =+ do packed <- sDelay sym (packBitmap sym sz bs)+ pure (BitmapVal sz packed bs)++{-# INLINE joinWordVal #-}+joinWordVal :: Backend sym => sym -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)+joinWordVal sym wv1 wv2 =+ let fallback = fallbackWordJoin sym wv1 wv2 in+ case (wv1, wv2) of+ (WordVal w1, WordVal w2) ->+ WordVal <$> joinWord sym w1 w2++ (ThunkWordVal _ m1, _) ->+ isReady sym m1 >>= \case+ Just x -> joinWordVal sym x wv2+ Nothing -> fallback++ (_,ThunkWordVal _ m2) ->+ isReady sym m2 >>= \case+ Just x -> joinWordVal sym wv1 x+ Nothing -> fallback++ (WordVal w1, BitmapVal _ packed2 _) ->+ isReady sym packed2 >>= \case+ Just w2 -> WordVal <$> joinWord sym w1 w2+ Nothing -> fallback++ (BitmapVal _ packed1 _, WordVal w2) ->+ isReady sym packed1 >>= \case+ Just w1 -> WordVal <$> joinWord sym w1 w2+ Nothing -> fallback++ (BitmapVal _ packed1 _, BitmapVal _ packed2 _) ->+ do r1 <- isReady sym packed1+ r2 <- isReady sym packed2+ case (r1,r2) of+ (Just w1, Just w2) -> WordVal <$> joinWord sym w1 w2+ _ -> fallback++{-# INLINE fallbackWordJoin #-}+fallbackWordJoin :: Backend sym => sym -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)+fallbackWordJoin sym w1 w2 =+ do let n1 = wordValueSize sym w1+ let n2 = wordValueSize sym w2+ let len = n1 + n2+ packed <- sDelay sym+ (do a <- asWordVal sym w1+ b <- asWordVal sym w2+ joinWord sym a b)+ let bs = concatSeqMap n1 (asBitsMap sym w1) (asBitsMap sym w2)+ pure (BitmapVal len packed bs)+++{-# INLINE takeWordVal #-}+takeWordVal ::+ Backend sym =>+ sym ->+ Integer ->+ Integer ->+ WordValue sym ->+ SEval sym (WordValue sym)+takeWordVal sym leftWidth rigthWidth (WordVal w) =+ do (lw, _rw) <- splitWord sym leftWidth rigthWidth w+ pure (WordVal lw)++takeWordVal sym leftWidth rightWidth (ThunkWordVal _ m) =+ isReady sym m >>= \case+ Just w -> takeWordVal sym leftWidth rightWidth w+ Nothing ->+ do m' <- sDelay sym (takeWordVal sym leftWidth rightWidth =<< m)+ return (ThunkWordVal leftWidth m')++takeWordVal sym leftWidth rightWidth (BitmapVal _n packed xs) =+ isReady sym packed >>= \case+ Just w -> do (lw, _rw) <- splitWord sym leftWidth rightWidth w+ pure (WordVal lw)+ Nothing -> bitmapWordVal sym leftWidth xs++{-# INLINE dropWordVal #-}+dropWordVal ::+ Backend sym =>+ sym ->+ Integer ->+ Integer ->+ WordValue sym ->+ SEval sym (WordValue sym)+dropWordVal sym leftWidth rigthWidth (WordVal w) =+ do (_lw, rw) <- splitWord sym leftWidth rigthWidth w+ pure (WordVal rw)++dropWordVal sym leftWidth rightWidth (ThunkWordVal _ m) =+ isReady sym m >>= \case+ Just w -> dropWordVal sym leftWidth rightWidth w+ Nothing ->+ do m' <- sDelay sym (dropWordVal sym leftWidth rightWidth =<< m)+ return (ThunkWordVal rightWidth m')++dropWordVal sym leftWidth rightWidth (BitmapVal _n packed xs) =+ isReady sym packed >>= \case+ Just w -> do (_lw, rw) <- splitWord sym leftWidth rightWidth w+ pure (WordVal rw)+ Nothing ->+ do let rxs = dropSeqMap leftWidth xs+ bitmapWordVal sym rightWidth rxs++{-# INLINE extractWordVal #-}++-- | Extract a subsequence of bits from a @WordValue@.+-- The first integer argument is the number of bits in the+-- resulting word. The second integer argument is the+-- number of less-significant digits to discard. Stated another+-- way, the operation `extractWordVal n i w` is equivalent to+-- first shifting `w` right by `i` bits, and then truncating to+-- `n` bits.+extractWordVal ::+ Backend sym =>+ sym ->+ Integer ->+ Integer ->+ WordValue sym ->+ SEval sym (WordValue sym)+extractWordVal sym len start (WordVal w) =+ WordVal <$> extractWord sym len start w+extractWordVal sym len start (ThunkWordVal _n m) =+ isReady sym m >>= \case+ Just w -> extractWordVal sym len start w+ Nothing ->+ do m' <- sDelay sym (extractWordVal sym len start =<< m)+ pure (ThunkWordVal len m')+extractWordVal sym len start (BitmapVal n packed xs) =+ isReady sym packed >>= \case+ Just w -> WordVal <$> extractWord sym len start w+ Nothing ->+ do let xs' = dropSeqMap (n - start - len) xs+ bitmapWordVal sym len xs'++{-# INLINE wordValLogicOp #-}++wordValLogicOp ::+ Backend sym =>+ sym ->+ (SBit sym -> SBit sym -> SEval sym (SBit sym)) ->+ (SWord sym -> SWord sym -> SEval sym (SWord sym)) ->+ WordValue sym ->+ WordValue sym ->+ SEval sym (WordValue sym)+wordValLogicOp _sym _ wop (WordVal w1) (WordVal w2) = WordVal <$> wop w1 w2++wordValLogicOp sym bop wop (WordVal w1) (BitmapVal n2 packed2 bs2) =+ isReady sym packed2 >>= \case+ Just w2 -> WordVal <$> wop w1 w2+ Nothing -> bitmapWordVal sym n2 =<< zipSeqMap sym bop (Nat n2) (unpackBitmap sym w1) bs2++wordValLogicOp sym bop wop (BitmapVal n1 packed1 bs1) (WordVal w2) =+ isReady sym packed1 >>= \case+ Just w1 -> WordVal <$> wop w1 w2+ Nothing -> bitmapWordVal sym n1 =<< zipSeqMap sym bop (Nat n1) bs1 (unpackBitmap sym w2)++wordValLogicOp sym bop wop (BitmapVal n1 packed1 bs1) (BitmapVal _n2 packed2 bs2) =+ do r1 <- isReady sym packed1+ r2 <- isReady sym packed2+ case (r1,r2) of+ (Just w1, Just w2) -> WordVal <$> wop w1 w2+ _ -> bitmapWordVal sym n1 =<< zipSeqMap sym bop (Nat n1) bs1 bs2++wordValLogicOp sym bop wop (ThunkWordVal _ m1) w2 =+ do w1 <- m1+ wordValLogicOp sym bop wop w1 w2++wordValLogicOp sym bop wop w1 (ThunkWordVal _ m2) =+ do w2 <- m2+ wordValLogicOp sym bop wop w1 w2++{-# INLINE wordValUnaryOp #-}+wordValUnaryOp ::+ Backend sym =>+ sym ->+ (SBit sym -> SEval sym (SBit sym)) ->+ (SWord sym -> SEval sym (SWord sym)) ->+ WordValue sym ->+ SEval sym (WordValue sym)+wordValUnaryOp _ _ wop (WordVal w) = WordVal <$> wop w+wordValUnaryOp sym bop wop (ThunkWordVal _ m) = wordValUnaryOp sym bop wop =<< m+wordValUnaryOp sym bop wop (BitmapVal n packed xs) =+ isReady sym packed >>= \case+ Just w -> WordVal <$> wop w+ Nothing -> bitmapWordVal sym n =<< mapSeqMap sym bop (Nat n) xs++{-# SPECIALIZE joinWords ::+ Concrete ->+ Integer ->+ Integer ->+ SeqMap Concrete (WordValue Concrete)->+ SEval Concrete (WordValue Concrete)+ #-}+joinWords :: forall sym.+ Backend sym =>+ sym ->+ Integer ->+ Integer ->+ SeqMap sym (WordValue sym) ->+ SEval sym (WordValue sym)++-- small enough to pack+joinWords sym nParts nEach xs | nParts * nEach < largeBitSize =+ do z <- wordLit sym 0 0+ loop (wordVal z) (enumerateSeqMap nParts xs)++ where+ loop :: WordValue sym -> [SEval sym (WordValue sym)] -> SEval sym (WordValue sym)+ loop !wv [] = pure wv+ loop !wv (w : ws) =+ do w' <- delayWordValue sym nEach w+ wv' <- joinWordVal sym wv w'+ loop wv' ws++-- too large to pack+joinWords sym nParts nEach xs = bitmapWordVal sym (nParts * nEach) zs+ where+ zs = indexSeqMap $ \i ->+ do let (q,r) = divMod i nEach+ ys <- lookupSeqMap xs q+ indexWordValue sym ys r++reverseWordVal :: Backend sym => sym -> WordValue sym -> SEval sym (WordValue sym)+reverseWordVal sym w =+ let m = wordValueSize sym w in+ bitmapWordVal sym m <$> reverseSeqMap m $ asBitsMap sym w++wordValAsLit :: Backend sym => sym -> WordValue sym -> SEval sym (Maybe Integer)+wordValAsLit sym (WordVal w) = pure (snd <$> wordAsLit sym w)+wordValAsLit sym (ThunkWordVal _ m) =+ isReady sym m >>= \case+ Just v -> wordValAsLit sym v+ Nothing -> pure Nothing+wordValAsLit sym (BitmapVal _ packed _) =+ isReady sym packed >>= \case+ Just w -> pure (snd <$> wordAsLit sym w)+ Nothing -> pure Nothing++-- | Force a word value into packed word form+asWordVal :: Backend sym => sym -> WordValue sym -> SEval sym (SWord sym)+asWordVal _ (WordVal w) = return w+asWordVal sym (ThunkWordVal _ m) = asWordVal sym =<< m+asWordVal _ (BitmapVal _ packed _) = packed++wordValueEqualsInteger :: forall sym. Backend sym =>+ sym ->+ WordValue sym ->+ Integer ->+ SEval sym (SBit sym)+wordValueEqualsInteger sym wv i+ | wordValueSize sym wv < widthInteger i = return (bitLit sym False)+ | otherwise = loop wv++ where+ loop (ThunkWordVal _ m) = loop =<< m+ loop (WordVal w) = wordEq sym w =<< wordLit sym (wordLen sym w) i+ loop (BitmapVal n packed bs) =+ isReady sym packed >>= \case+ Just w -> loop (WordVal w)+ Nothing -> bitsAre i =<< sequence (enumerateSeqMap n (reverseSeqMap n bs))++ -- NB little-endian sequence of bits+ bitsAre :: Integer -> [SBit sym] -> SEval sym (SBit sym)+ bitsAre !n [] = return (bitLit sym (n == 0))+ bitsAre !n (b:bs) =+ do pb <- bitIs (testBit n 0) b+ pbs <- bitsAre (n `shiftR` 1) bs+ bitAnd sym pb pbs++ bitIs :: Bool -> SBit sym -> SEval sym (SBit sym)+ bitIs b x = if b then pure x else bitComplement sym x++asWordList :: forall sym. Backend sym => sym -> [WordValue sym] -> SEval sym (Maybe [SWord sym])+asWordList sym = loop id+ where+ loop :: ([SWord sym] -> [SWord sym]) -> [WordValue sym] -> SEval sym (Maybe [SWord sym])+ loop f [] = pure (Just (f []))+ loop f (WordVal x : vs) = loop (f . (x:)) vs+ loop f (ThunkWordVal _ m : vs) =+ isReady sym m >>= \case+ Just m' -> loop f (m' : vs)+ Nothing -> pure Nothing+ loop f (BitmapVal _ packed _ : vs) =+ isReady sym packed >>= \case+ Just x -> loop (f . (x:)) vs+ Nothing -> pure Nothing++-- | Force a word value into a sequence of bits+asBitsMap :: Backend sym => sym -> WordValue sym -> SeqMap sym (SBit sym)+asBitsMap _ (BitmapVal _ _ xs) = xs+asBitsMap sym (WordVal w) = indexSeqMap $ \i -> wordBit sym w i+asBitsMap sym (ThunkWordVal _ m) =+ indexSeqMap $ \i ->+ do mp <- asBitsMap sym <$> (unwindThunks m)+ lookupSeqMap mp i++-- | Turn a word value into a sequence of bits, forcing each bit.+-- The sequence is returned in big-endian order.+enumerateWordValue :: Backend sym => sym -> WordValue sym -> SEval sym [SBit sym]+enumerateWordValue sym (WordVal w) = unpackWord sym w+enumerateWordValue sym (ThunkWordVal _ m) = enumerateWordValue sym =<< m+ -- TODO? used the packed value if it is ready?+enumerateWordValue _ (BitmapVal n _ xs) = sequence (enumerateSeqMap n xs)++-- | Turn a word value into a sequence of bits, forcing each bit.+-- The sequence is returned in reverse of the usual order, which is little-endian order.+enumerateWordValueRev :: Backend sym => sym -> WordValue sym -> SEval sym [SBit sym]+enumerateWordValueRev sym (WordVal w) = reverse <$> unpackWord sym w+enumerateWordValueRev sym (ThunkWordVal _ m) = enumerateWordValueRev sym =<< m+ -- TODO? used the packed value if it is ready?+enumerateWordValueRev _ (BitmapVal n _ xs) = sequence (enumerateSeqMap n (reverseSeqMap n xs))+++enumerateIndexSegments :: Backend sym => sym -> WordValue sym -> SEval sym [IndexSegment sym]+enumerateIndexSegments _sym (WordVal w) = pure [WordIndexSegment w]+enumerateIndexSegments sym (ThunkWordVal _ m) = enumerateIndexSegments sym =<< m+enumerateIndexSegments sym (BitmapVal n packed xs) =+ isReady sym packed >>= \case+ Just w -> pure [WordIndexSegment w]+ Nothing -> traverse (BitIndexSegment <$>) (enumerateSeqMap n xs)++{-# SPECIALIZE bitsValueLessThan ::+ Concrete ->+ Integer ->+ [SBit Concrete] ->+ Integer ->+ SEval Concrete (SBit Concrete)+ #-}+bitsValueLessThan ::+ Backend sym =>+ sym ->+ Integer {- ^ bit-width -} ->+ [SBit sym] {- ^ big-endian list of index bits -} ->+ Integer {- ^ Upper bound to test against -} ->+ SEval sym (SBit sym)+bitsValueLessThan sym _w [] _n = pure $ bitLit sym False+bitsValueLessThan sym w (b:bs) n+ | nbit =+ do notb <- bitComplement sym b+ bitOr sym notb =<< bitsValueLessThan sym (w-1) bs n+ | otherwise =+ do notb <- bitComplement sym b+ bitAnd sym notb =<< bitsValueLessThan sym (w-1) bs n+ where+ nbit = testBit n (fromInteger (w-1))+++assertWordValueInBounds ::+ Backend sym => sym -> Integer -> WordValue sym -> SEval sym ()++-- Can't index out of bounds for a sequence that is+-- longer than the expressible index values+assertWordValueInBounds sym n idx+ | n >= 2^(wordValueSize sym idx)+ = return ()++assertWordValueInBounds sym n (WordVal idx)+ | Just (_w,i) <- wordAsLit sym idx+ = unless (i < n) (raiseError sym (InvalidIndex (Just i)))++-- If the index is a packed word, test that it+-- is less than the concrete value of n, which+-- fits into w bits because of the above test.+assertWordValueInBounds sym n (WordVal idx) =+ do n' <- wordLit sym (wordLen sym idx) n+ p <- wordLessThan sym idx n'+ assertSideCondition sym p (InvalidIndex Nothing)++-- Force thunks+assertWordValueInBounds sym n (ThunkWordVal _ m) =+ assertWordValueInBounds sym n =<< m++-- If the index is an unpacked word, force all the bits+-- and compute the unsigned less-than test directly.+assertWordValueInBounds sym n (BitmapVal sz packed bits) =+ isReady sym packed >>= \case+ Just w -> assertWordValueInBounds sym n (WordVal w)+ Nothing ->+ do bitsList <- sequence (enumerateSeqMap sz bits)+ p <- bitsValueLessThan sym sz bitsList n+ assertSideCondition sym p (InvalidIndex Nothing)++delayWordValue :: Backend sym => sym -> Integer -> SEval sym (WordValue sym) -> SEval sym (WordValue sym)+delayWordValue sym sz m =+ isReady sym m >>= \case+ Just w -> pure w+ Nothing -> ThunkWordVal sz <$> sDelay sym (unwindThunks m)++-- If we are calling this, we know the spine of the word value has been+-- demanded, so we unwind any chains of `ThunkWordValue` that may have built up.+unwindThunks :: Backend sym => SEval sym (WordValue sym) -> SEval sym (WordValue sym)+unwindThunks m =+ m >>= \case+ ThunkWordVal _ m' -> unwindThunks m'+ x -> pure x++{-# INLINE shiftWordByInteger #-}+shiftWordByInteger ::+ Backend sym =>+ sym ->+ (SWord sym -> SWord sym -> SEval sym (SWord sym)) + {- ^ operation on word values -} ->+ (Integer -> Integer -> Maybe Integer)+ {- ^ reindexing operation -} ->+ WordValue sym {- ^ word value to shift -} ->+ SInteger sym {- ^ shift amount, assumed to be in range [0,len] -} ->+ SEval sym (WordValue sym)++shiftWordByInteger sym wop reindex x idx =+ case x of+ ThunkWordVal w wm ->+ isReady sym wm >>= \case+ Just x' -> shiftWordByInteger sym wop reindex x' idx+ Nothing ->+ do m' <- sDelay sym+ (do x' <- wm+ shiftWordByInteger sym wop reindex x' idx)+ return (ThunkWordVal w m')++ WordVal x' -> WordVal <$> (wop x' =<< wordFromInt sym (wordLen sym x') idx)++ BitmapVal n packed bs0 ->+ isReady sym packed >>= \case+ Just w -> shiftWordByInteger sym wop reindex (WordVal w) idx+ Nothing ->+ bitmapWordVal sym n =<<+ shiftSeqByInteger sym (iteBit sym) reindex (pure (bitLit sym False)) (Nat n) bs0 idx+++{-# INLINE shiftWordByWord #-}+shiftWordByWord ::+ Backend sym =>+ sym ->+ (SWord sym -> SWord sym -> SEval sym (SWord sym))+ {- ^ operation on word values -} ->+ (Integer -> Integer -> Maybe Integer)+ {- ^ reindexing operation -} ->+ WordValue sym {- ^ value to shift -} ->+ WordValue sym {- ^ amount to shift -} ->+ SEval sym (WordValue sym)+shiftWordByWord sym wop reindex x idx =+ case x of+ ThunkWordVal w wm ->+ isReady sym wm >>= \case+ Just wm' -> shiftWordByWord sym wop reindex wm' idx+ Nothing ->+ do m' <- sDelay sym (do wm' <- wm+ shiftWordByWord sym wop reindex wm' idx)+ return (ThunkWordVal w m')++ WordVal x' -> WordVal <$> (wop x' =<< asWordVal sym idx)++ BitmapVal n packed bs0 ->+ isReady sym packed >>= \case+ Just w -> shiftWordByWord sym wop reindex (WordVal w) idx+ Nothing ->+ bitmapWordVal sym n =<<+ shiftSeqByWord sym (iteBit sym) reindex (pure (bitLit sym False)) (Nat n) bs0 idx+++{-# INLINE updateWordByWord #-}+updateWordByWord ::+ Backend sym =>+ sym ->+ IndexDirection ->+ WordValue sym {- ^ value to update -} ->+ WordValue sym {- ^ index to update at -} ->+ SEval sym (SBit sym) {- ^ fresh bit -} ->+ SEval sym (WordValue sym)+updateWordByWord sym dir w0 idx bitval =+ wordValAsLit sym idx >>= \case+ Just j ->+ let sz = wordValueSize sym w0 in+ case dir of+ IndexForward -> updateWordValue sym w0 j bitval+ IndexBackward -> updateWordValue sym w0 (sz - j - 1) bitval+ Nothing -> loop w0++ where+ loop (ThunkWordVal sz m) =+ isReady sym m >>= \case+ Just w' -> loop w'+ Nothing -> delayWordValue sym sz (loop =<< m)++ loop (BitmapVal sz packed bs) =+ isReady sym packed >>= \case+ Just w -> loop (WordVal w)+ Nothing ->+ case dir of+ IndexForward ->+ bitmapWordVal sym sz $ indexSeqMap $ \i ->+ do b <- wordValueEqualsInteger sym idx i+ mergeEval sym (iteBit sym) b bitval (lookupSeqMap bs i)+ IndexBackward ->+ bitmapWordVal sym sz $ indexSeqMap $ \i ->+ do b <- wordValueEqualsInteger sym idx (sz - i - 1)+ mergeEval sym (iteBit sym) b bitval (lookupSeqMap bs i)++ loop (WordVal wv) = WordVal <$>+ -- TODO, this is too strict in bit+ do let sz = wordLen sym wv+ b <- bitval+ msk <- case dir of+ IndexForward ->+ do highbit <- wordLit sym sz (bit (fromInteger (sz-1)))+ wordShiftRight sym highbit =<< asWordVal sym idx+ IndexBackward ->+ do lowbit <- wordLit sym sz 1+ wordShiftLeft sym lowbit =<< asWordVal sym idx+ case bitAsLit sym b of+ Just True -> wordOr sym wv msk+ Just False -> wordAnd sym wv =<< wordComplement sym msk+ Nothing ->+ do zro <- wordLit sym sz 0+ one <- wordComplement sym zro+ q <- iteWord sym b one zro+ w' <- wordAnd sym wv =<< wordComplement sym msk+ wordXor sym w' =<< wordAnd sym msk q+++{-# INLINE shiftSeqByWord #-}+shiftSeqByWord ::+ Backend sym =>+ sym ->+ (SBit sym -> a -> a -> SEval sym a)+ {- ^ if/then/else operation of values -} ->+ (Integer -> Integer -> Maybe Integer)+ {- ^ reindexing operation -} ->+ SEval sym a {- ^ zero value -} ->+ Nat' {- ^ size of the sequence -} ->+ SeqMap sym a {- ^ sequence to shift -} ->+ WordValue sym {- ^ shift amount -} ->+ SEval sym (SeqMap sym a)+shiftSeqByWord sym merge reindex zro sz xs idx =+ wordValAsLit sym idx >>= \case+ Just j -> shiftOp xs j+ Nothing ->+ do idx_segs <- enumerateIndexSegments sym idx+ barrelShifter sym merge shiftOp sz xs idx_bits idx_segs+ where+ idx_bits = wordValueSize sym idx++ shiftOp vs shft =+ pure $ indexSeqMap $ \i ->+ case reindex i shft of+ Nothing -> zro+ Just i' -> lookupSeqMap vs i'++-- | Compute the size of a word value+-- TODO, can we get rid of this? If feels like it should be+-- unnecessary.+wordValueSize :: Backend sym => sym -> WordValue sym -> Integer+wordValueSize sym (WordVal w) = wordLen sym w+wordValueSize _ (ThunkWordVal n _) = n+wordValueSize _ (BitmapVal n _ _) = n++-- | Select an individual bit from a word value+indexWordValue :: Backend sym => sym -> WordValue sym -> Integer -> SEval sym (SBit sym)+indexWordValue sym (ThunkWordVal _ m) idx = do m' <- m ; indexWordValue sym m' idx+indexWordValue sym (WordVal w) idx+ | 0 <= idx && idx < wordLen sym w = wordBit sym w idx+ | otherwise = invalidIndex sym idx+indexWordValue sym (BitmapVal n _packed xs) idx+ | 0 <= idx && idx < n = lookupSeqMap xs idx+ | otherwise = invalidIndex sym idx++-- | Produce a new 'WordValue' from the one given by updating the @i@th bit with the+-- given bit value.+updateWordValue :: Backend sym =>+ sym -> WordValue sym -> Integer -> SEval sym (SBit sym) -> SEval sym (WordValue sym)+updateWordValue sym wv0 idx b = loop wv0+ where+ loop (ThunkWordVal sz m) =+ isReady sym m >>= \case+ Just w -> loop w+ Nothing -> delayWordValue sym sz (loop =<< m)++ loop (WordVal w)+ | idx < 0 || idx >= wordLen sym w = invalidIndex sym idx+ | otherwise =+ isReady sym b >>= \case+ Just b' -> WordVal <$> wordUpdate sym w idx b'+ Nothing ->+ do let bs = unpackBitmap sym w+ bitmapWordVal sym (wordLen sym w) $ updateSeqMap bs idx b++ loop (BitmapVal sz packed bs)+ | 0 <= idx && idx < sz =+ isReady sym packed >>= \case+ Just w -> loop (WordVal w)+ Nothing -> bitmapWordVal sym sz $ updateSeqMap bs idx b+ | otherwise = invalidIndex sym idx++{-# INLINE mergeWord #-}+mergeWord :: Backend sym =>+ sym ->+ SBit sym ->+ WordValue sym ->+ WordValue sym ->+ SEval sym (WordValue sym)+mergeWord sym c (ThunkWordVal _ m1) (ThunkWordVal _ m2) =+ mergeWord' sym c (unwindThunks m1) (unwindThunks m2)+mergeWord sym c (ThunkWordVal _ m1) w2 =+ mergeWord' sym c (unwindThunks m1) (pure w2)+mergeWord sym c w1 (ThunkWordVal _ m2) =+ mergeWord' sym c (pure w1) (unwindThunks m2)++mergeWord sym c (WordVal w1) (WordVal w2) =+ WordVal <$> iteWord sym c w1 w2++mergeWord sym c (BitmapVal n1 packed1 bs1) (WordVal w2) =+ isReady sym packed1 >>= \case+ Just w1 -> WordVal <$> iteWord sym c w1 w2+ Nothing -> mergeBitmaps sym c n1 bs1 (unpackBitmap sym w2)++mergeWord sym c (WordVal w1) (BitmapVal n2 packed2 bs2) =+ isReady sym packed2 >>= \case+ Just w2 -> WordVal <$> iteWord sym c w1 w2+ Nothing -> mergeBitmaps sym c n2 (unpackBitmap sym w1) bs2++mergeWord sym c (BitmapVal n1 packed1 bs1) (BitmapVal _n2 packed2 bs2) =+ do r1 <- isReady sym packed1+ r2 <- isReady sym packed2+ case (r1,r2) of+ (Just w1, Just w2) -> WordVal <$> iteWord sym c w1 w2+ _ -> mergeBitmaps sym c n1 bs1 bs2++mergeBitmaps :: Backend sym =>+ sym ->+ SBit sym ->+ Integer ->+ SeqMap sym (SBit sym) ->+ SeqMap sym (SBit sym) ->+ SEval sym (WordValue sym)+mergeBitmaps sym c sz bs1 bs2 =+ do bs <- memoMap sym (Nat sz) (mergeSeqMap sym (iteBit sym) c bs1 bs2)+ bitmapWordVal sym sz bs++{-# INLINE mergeWord' #-}+mergeWord' :: Backend sym =>+ sym ->+ SBit sym ->+ SEval sym (WordValue sym) ->+ SEval sym (WordValue sym) ->+ SEval sym (WordValue sym)+mergeWord' sym c x y+ | Just b <- bitAsLit sym c = if b then x else y+ | otherwise = mergeEval sym (mergeWord sym) c x y
src/Cryptol/Eval.hs view
@@ -40,7 +40,9 @@ import Cryptol.Backend import Cryptol.Backend.Concrete( Concrete(..) ) import Cryptol.Backend.Monad-import Cryptol.Eval.Generic ( iteValue )+import Cryptol.Backend.SeqMap+import Cryptol.Backend.WordValue+ import Cryptol.Eval.Env import Cryptol.Eval.Prims import Cryptol.Eval.Type@@ -122,14 +124,14 @@ -- NB, even if the list cannot be packed, we must use `VWord` -- when the element type is `Bit`. | isTBit tyv -> {-# SCC "evalExpr->Elist/bit" #-}- return $ VWord len $- case tryFromBits sym vs of- Just w -> WordVal <$> w- Nothing -> do xs <- mapM (sDelay sym) vs- return $ LargeBitsVal len $ finiteSeqMap xs+ VWord len <$>+ (tryFromBits sym vs >>= \case+ Just w -> pure (wordVal w)+ Nothing -> do xs <- mapM (\x -> sDelay sym (fromVBit <$> x)) vs+ bitmapWordVal sym len $ finiteSeqMap sym xs) | otherwise -> {-# SCC "evalExpr->EList" #-} do xs <- mapM (sDelay sym) vs- return $ VSeq len $ finiteSeqMap xs+ return $ VSeq len $ finiteSeqMap sym xs where tyv = evalValType (envTypes env) ty vs = map eval es@@ -362,186 +364,12 @@ GenEvalEnv sym -> (Name, Schema, SEval sym (GenValue sym), SEval sym (GenValue sym) -> SEval sym ()) -> SEval sym ()-fillHole sym env (nm, sch, _, fill) = do+fillHole _sym env (nm, _sch, _, fill) = do case lookupVar nm env of- Just (Right v)- | isValueType env sch ->- fill =<< sDelayFill sym v- (Just (etaDelay sym env sch v))- (show (ppLocName nm))-- | otherwise -> fill (etaDelay sym env sch v)-+ Just (Right v) -> fill v _ -> evalPanic "fillHole" ["Recursive definition not completed", show (ppLocName nm)] --- | 'Value' types are non-polymorphic types recursive constructed from--- bits, finite sequences, tuples and records. Types of this form can--- be implemented rather more efficiently than general types because we can--- rely on the 'delayFill' operation to build a thunk that falls back on performing--- eta-expansion rather than doing it eagerly.-isValueType :: GenEvalEnv sym -> Schema -> Bool-isValueType env Forall{ sVars = [], sProps = [], sType = t0 }- = go (evalValType (envTypes env) t0)- where- go TVBit = True- go (TVSeq _ x) = go x- go (TVTuple xs) = and (map go xs)- go (TVRec xs) = and (fmap go xs)- go (TVNewtype _ _ xs) = and (fmap go xs)- go _ = False -isValueType _ _ = False---{-# SPECIALIZE etaWord ::- Concrete ->- Integer ->- SEval Concrete (GenValue Concrete) ->- SEval Concrete (WordValue Concrete)- #-}---- | Eta-expand a word value. This forces an unpacked word representation.-etaWord ::- Backend sym =>- sym ->- Integer ->- SEval sym (GenValue sym) ->- SEval sym (WordValue sym)-etaWord sym n val = do- w <- sDelay sym (fromWordVal "during eta-expansion" =<< val)- xs <- memoMap sym $ IndexSeqMap $ \i ->- do w' <- w; VBit <$> indexWordValue sym w' i- pure $ LargeBitsVal n xs--{-# SPECIALIZE etaDelay ::- Concrete ->- GenEvalEnv Concrete ->- Schema ->- SEval Concrete (GenValue Concrete) ->- SEval Concrete (GenValue Concrete)- #-}---- | Given a simulator value and its type, fully eta-expand the value. This--- is a type-directed pass that always produces a canonical value of the--- expected shape. Eta expansion of values is sometimes necessary to ensure--- the correct evaluation semantics of recursive definitions. Otherwise,--- expressions that should be expected to produce well-defined values in the--- denotational semantics will fail to terminate instead.-etaDelay ::- Backend sym =>- sym ->- GenEvalEnv sym ->- Schema ->- SEval sym (GenValue sym) ->- SEval sym (GenValue sym)-etaDelay sym env0 Forall{ sVars = vs0, sType = tp0 } = goTpVars env0 vs0- where- goTpVars env [] val =- do stk <- sGetCallStack sym- go stk (evalValType (envTypes env) tp0) val- goTpVars env (v:vs) val =- case tpKind v of- KType -> tlam sym $ \t ->- goTpVars (bindType (tpVar v) (Right t) env) vs ( ($t) . fromVPoly sym =<< val )- KNum -> nlam sym $ \n ->- goTpVars (bindType (tpVar v) (Left n) env) vs ( ($n) . fromVNumPoly sym =<< val )- k -> panic "[Eval] etaDelay" ["invalid kind on type abstraction", show k]-- go stk tp x | isReady sym x = x >>= \case- VBit{} -> x- VInteger{} -> x- VWord{} -> x- VRational{} -> x- VFloat{} -> x- VSeq n xs ->- case tp of- TVSeq _nt el -> return $ VSeq n $ IndexSeqMap $ \i -> go stk el (lookupSeqMap xs i)- _ -> evalPanic "type mismatch during eta-expansion" ["Expected sequence type, but got " ++ show tp]-- VStream xs ->- case tp of- TVStream el -> return $ VStream $ IndexSeqMap $ \i -> go stk el (lookupSeqMap xs i)- _ -> evalPanic "type mismatch during eta-expansion" ["Expected stream type, but got " ++ show tp]-- VTuple xs ->- case tp of- TVTuple ts | length ts == length xs -> return $ VTuple (zipWith (go stk) ts xs)- _ -> evalPanic "type mismatch during eta-expansion" ["Expected tuple type with " ++ show (length xs)- ++ " elements, but got " ++ show tp]-- VRecord fs ->- case tp of- TVNewtype _ _ fts ->- do let res = zipRecords (\_ v t -> go stk t v) fs fts- case res of- Left (Left f) -> evalPanic "type mismatch during eta-expansion" ["missing field " ++ show f]- Left (Right f) -> evalPanic "type mismatch during eta-expansion" ["unexpected field " ++ show f]- Right fs' -> return (VRecord fs')- TVRec fts ->- do let res = zipRecords (\_ v t -> go stk t v) fs fts- case res of- Left (Left f) -> evalPanic "type mismatch during eta-expansion" ["missing field " ++ show f]- Left (Right f) -> evalPanic "type mismatch during eta-expansion" ["unexpected field " ++ show f]- Right fs' -> return (VRecord fs')- _ -> evalPanic "type mismatch during eta-expansion" ["Expected record type, but got " ++ show tp]-- f@VFun{} ->- case tp of- TVFun _t1 t2 -> lam sym $ \a -> go stk t2 (fromVFun sym f a)- _ -> evalPanic "type mismatch during eta-expansion" ["Expected function type but got " ++ show tp]-- VPoly{} ->- evalPanic "type mismatch during eta-expansion" ["Encountered polymorphic value"]-- VNumPoly{} ->- evalPanic "type mismatch during eta-expansion" ["Encountered numeric polymorphic value"]-- go stk tp v = sWithCallStack sym stk $- case tp of- TVBit -> v- TVInteger -> v- TVFloat {} -> v- TVIntMod _ -> v- TVRational -> v- TVArray{} -> v-- TVSeq n TVBit ->- do w <- sDelayFill sym (fromWordVal "during eta-expansion" =<< v) (Just (etaWord sym n v)) ""- return $ VWord n w-- TVSeq n el ->- do x' <- sDelay sym (fromSeq "during eta-expansion" =<< v)- return $ VSeq n $ IndexSeqMap $ \i -> do- go stk el (flip lookupSeqMap i =<< x')-- TVStream el ->- do x' <- sDelay sym (fromSeq "during eta-expansion" =<< v)- return $ VStream $ IndexSeqMap $ \i ->- go stk el (flip lookupSeqMap i =<< x')-- TVFun _t1 t2 ->- do v' <- sDelay sym (fromVFun sym <$> v)- lam sym $ \a -> go stk t2 ( ($a) =<< v' )-- TVTuple ts ->- do let n = length ts- v' <- sDelay sym (fromVTuple <$> v)- return $ VTuple $- [ go stk t =<< (flip genericIndex i <$> v')- | i <- [0..(n-1)]- | t <- ts- ]-- TVRec fs ->- do v' <- sDelay sym (fromVRecord <$> v)- let err f = evalPanic "expected record value with field" [show f]- let eta f t = go stk t =<< (fromMaybe (err f) . lookupField f <$> v')- return $ VRecord (mapWithFieldName eta fs)-- TVAbstract {} -> v-- TVNewtype _ _ body -> go stk (TVRec body) v- {-# SPECIALIZE declHole :: Concrete -> Decl ->@@ -600,9 +428,11 @@ SEval Concrete (GenValue Concrete) #-} --- | Apply the the given "selector" form to the given value. This function pushes--- tuple and record selections pointwise down into other value constructs--- (e.g., streams and functions).+-- | Apply the the given "selector" form to the given value. Note that+-- selectors are expected to apply only to values of the right type,+-- e.g. tuple selectors expect only tuple values. The lifting of+-- tuple an record selectors over functions and sequences has already+-- been resolved earlier in the typechecker. evalSel :: Backend sym => sym ->@@ -636,7 +466,7 @@ case v of VSeq _ vs -> lookupSeqMap vs (toInteger n) VStream vs -> lookupSeqMap vs (toInteger n)- VWord _ wv -> VBit <$> (flip (indexWordValue sym) (toInteger n) =<< wv)+ VWord _ wv -> VBit <$> indexWordValue sym wv (toInteger n) _ -> do vdoc <- ppValue sym defaultPPOpts val evalPanic "Cryptol.Eval.evalSel" [ "Unexpected value in list selection"@@ -685,8 +515,7 @@ case e of VSeq i mp -> pure $ VSeq i $ updateSeqMap mp n v VStream mp -> pure $ VStream $ updateSeqMap mp n v- VWord i m -> pure $ VWord i $ do m1 <- m- updateWordValue sym m1 n asBit+ VWord i m -> VWord i <$> updateWordValue sym m n asBit _ -> bad "Sequence update on a non-sequence." asBit = do res <- v@@ -776,7 +605,7 @@ SEval sym (GenValue sym) evalComp sym env len elty body ms = do lenv <- mconcat <$> mapM (branchEnvs sym (toListEnv env)) ms- mkSeq len elty <$> memoMap sym (IndexSeqMap $ \i -> do+ mkSeq sym len elty =<< memoMap sym len (indexSeqMap $ \i -> do evalExpr sym (evalListEnv lenv i) body) {-# SPECIALIZE branchEnvs ::@@ -794,24 +623,24 @@ ListEnv sym -> [Match] -> SEval sym (ListEnv sym)-branchEnvs sym env matches = foldM (evalMatch sym) env matches+branchEnvs sym env matches = snd <$> foldM (evalMatch sym) (1, env) matches {-# SPECIALIZE evalMatch :: (?range :: Range, ConcPrims) => Concrete ->- ListEnv Concrete ->+ (Integer, ListEnv Concrete) -> Match ->- SEval Concrete (ListEnv Concrete)+ SEval Concrete (Integer, ListEnv Concrete) #-} -- | Turn a match into the list of environments it represents. evalMatch :: (?range :: Range, EvalPrims sym) => sym ->- ListEnv sym ->+ (Integer, ListEnv sym) -> Match ->- SEval sym (ListEnv sym)-evalMatch sym lenv m = case m of+ SEval sym (Integer, ListEnv sym)+evalMatch sym (lsz, lenv) m = seq lsz $ case m of -- many envs From n l _ty expr ->@@ -819,16 +648,16 @@ -- Select from a sequence of finite length. This causes us to 'stutter' -- through our previous choices `nLen` times. Nat nLen -> do- vss <- memoMap sym $ IndexSeqMap $ \i -> evalExpr sym (evalListEnv lenv i) expr+ vss <- memoMap sym (Nat lsz) $ indexSeqMap $ \i -> evalExpr sym (evalListEnv lenv i) expr let stutter xs = \i -> xs (i `div` nLen) let lenv' = lenv { leVars = fmap stutter (leVars lenv) } let vs i = do let (q, r) = i `divMod` nLen lookupSeqMap vss q >>= \case- VWord _ w -> VBit <$> (flip (indexWordValue sym) r =<< w)+ VWord _ w -> VBit <$> indexWordValue sym w r VSeq _ xs' -> lookupSeqMap xs' r VStream xs' -> lookupSeqMap xs' r _ -> evalPanic "evalMatch" ["Not a list value"]- return $ bindVarList n vs lenv'+ return (lsz * nLen, bindVarList n vs lenv') -- Select from a sequence of infinite length. Note that this means we -- will never need to backtrack into previous branches. Thus, we can convert@@ -842,11 +671,13 @@ let env = EvalEnv allvars (leTypes lenv) xs <- evalExpr sym env expr let vs i = case xs of- VWord _ w -> VBit <$> (flip (indexWordValue sym) i =<< w)+ VWord _ w -> VBit <$> indexWordValue sym w i VSeq _ xs' -> lookupSeqMap xs' i VStream xs' -> lookupSeqMap xs' i _ -> evalPanic "evalMatch" ["Not a list value"]- return $ bindVarList n vs lenv'+ -- Selecting from an infinite list effectively resets the length of the+ -- list environment, so return 1 as the length+ return (1, bindVarList n vs lenv') where len = evalNumType (leTypes lenv) l@@ -854,7 +685,7 @@ -- XXX we don't currently evaluate these as though they could be recursive, as -- they are typechecked that way; the read environment to evalExpr is the same -- as the environment to bind a new name in.- Let d -> return $ bindVarList (dName d) (\i -> f (evalListEnv lenv i)) lenv+ Let d -> return (lsz, bindVarList (dName d) (\i -> f (evalListEnv lenv i)) lenv) where f env = case dDefinition d of
src/Cryptol/Eval/Concrete.hs view
@@ -26,7 +26,6 @@ ) where import Control.Monad (guard, zipWithM, foldM, mzero)-import Data.Bits (Bits(..)) import Data.Ratio(numerator,denominator) import Data.Word(Word32, Word64) import MonadLib( ChoiceT, findOne, lift )@@ -42,8 +41,10 @@ import Cryptol.Backend.Concrete import Cryptol.Backend.FloatHelpers import Cryptol.Backend.Monad+import Cryptol.Backend.SeqMap+import Cryptol.Backend.WordValue -import Cryptol.Eval.Generic hiding (logicShift)+import Cryptol.Eval.Generic import Cryptol.Eval.Prims import Cryptol.Eval.Type import Cryptol.Eval.Value@@ -110,7 +111,7 @@ do ses <- traverse (go b) =<< lift (sequence (enumerateSeqMap n svs)) pure $ EList ses (tValTy b) (TVSeq n TVBit, VWord _ wval) ->- do BV _ v <- lift (asWordVal Concrete =<< wval)+ do BV _ v <- lift (asWordVal Concrete wval) pure $ ETApp (ETApp (prim "number") (tNum v)) (tWord (tNum n)) (_,VStream{}) -> mzero@@ -125,7 +126,7 @@ panic "Cryptol.Eval.Concrete.toExpr" ["type mismatch:" , pretty (tValTy ty)- , render doc+ , show doc ] floatToExpr :: PrimMap -> AST.Type -> AST.Type -> FP.BigFloat -> AST.Expr@@ -159,24 +160,11 @@ Map.fromList $ map (\(n, v) -> (prelPrim n, v)) - [ (">>$" , {-# SCC "Prelude::(>>$)" #-}- sshrV)-- -- Shifts and rotates- , ("<<" , {-# SCC "Prelude::(<<)" #-}- logicShift shiftLW shiftLS)- , (">>" , {-# SCC "Prelude::(>>)" #-}- logicShift shiftRW shiftRS)- , ("<<<" , {-# SCC "Prelude::(<<<)" #-}- logicShift rotateLW rotateLS)- , (">>>" , {-# SCC "Prelude::(>>>)" #-}- logicShift rotateRW rotateRS)-- -- Indexing and updates- , ("@" , {-# SCC "Prelude::(@)" #-}- indexPrim sym indexFront_int indexFront_bits indexFront)+ [ -- Indexing and updates+ ("@" , {-# SCC "Prelude::(@)" #-}+ indexPrim sym IndexForward indexFront_int indexFront_segs) , ("!" , {-# SCC "Prelude::(!)" #-}- indexPrim sym indexBack_int indexBack_bits indexBack)+ indexPrim sym IndexBackward indexFront_int indexFront_segs) , ("update" , {-# SCC "Prelude::update" #-} updatePrim sym updateFront_word updateFront)@@ -194,7 +182,7 @@ F2.pmult (fromInteger (u+1)) x y else F2.pmult (fromInteger (v+1)) y x- in return . VWord (1+u+v) . pure . WordVal . mkBv (1+u+v) $! z)+ in return . VWord (1+u+v) . wordVal . mkBv (1+u+v) $! z) , ("pmod", PFinPoly \_u ->@@ -203,7 +191,7 @@ PWordFun \(BV _ m) -> PPrim do assertSideCondition sym (m /= 0) DivideByZero- return . VWord v . pure . WordVal . mkBv v $! F2.pmod (fromInteger w) x m)+ return . VWord v . wordVal . mkBv v $! F2.pmod (fromInteger w) x m) , ("pdiv", PFinPoly \_u ->@@ -212,7 +200,7 @@ PWordFun \(BV _ m) -> PPrim do assertSideCondition sym (m /= 0) DivideByZero- return . VWord w . pure . WordVal . mkBv w $! F2.pdiv (fromInteger w) x m)+ return . VWord w . wordVal . mkBv w $! F2.pdiv (fromInteger w) x m) ] @@ -230,7 +218,7 @@ PFinPoly \p -> PFun \s -> PFun \t ->- PPrim + PPrim do s' <- toProjectivePoint =<< s t' <- toProjectivePoint =<< t let r = PrimeEC.ec_add_nonzero (PrimeEC.primeModulus p) s' t'@@ -285,8 +273,8 @@ foldM (\st blk -> seq st (SHA.processSHA256Block st <$> (toSHA256Block =<< blk))) SHA.initialSHA224State blks let f :: Word32 -> Eval Value- f = pure . VWord 32 . pure . WordVal . BV 32 . toInteger- zs = finiteSeqMap (map f [w0,w1,w2,w3,w4,w5,w6])+ f = pure . VWord 32 . wordVal . BV 32 . toInteger+ zs = finiteSeqMap Concrete (map f [w0,w1,w2,w3,w4,w5,w6]) seq zs (pure (VSeq 7 zs))) , ("processSHA2_256", {-# SCC "SuiteB::processSHA2_256" #-}@@ -298,8 +286,8 @@ foldM (\st blk -> seq st (SHA.processSHA256Block st <$> (toSHA256Block =<< blk))) SHA.initialSHA256State blks let f :: Word32 -> Eval Value- f = pure . VWord 32 . pure . WordVal . BV 32 . toInteger- zs = finiteSeqMap (map f [w0,w1,w2,w3,w4,w5,w6,w7])+ f = pure . VWord 32 . wordVal . BV 32 . toInteger+ zs = finiteSeqMap Concrete (map f [w0,w1,w2,w3,w4,w5,w6,w7]) seq zs (pure (VSeq 8 zs))) , ("processSHA2_384", {-# SCC "SuiteB::processSHA2_384" #-}@@ -311,8 +299,8 @@ foldM (\st blk -> seq st (SHA.processSHA512Block st <$> (toSHA512Block =<< blk))) SHA.initialSHA384State blks let f :: Word64 -> Eval Value- f = pure . VWord 64 . pure . WordVal . BV 64 . toInteger- zs = finiteSeqMap (map f [w0,w1,w2,w3,w4,w5])+ f = pure . VWord 64 . wordVal . BV 64 . toInteger+ zs = finiteSeqMap Concrete (map f [w0,w1,w2,w3,w4,w5]) seq zs (pure (VSeq 6 zs))) , ("processSHA2_512", {-# SCC "SuiteB::processSHA2_512" #-}@@ -324,8 +312,8 @@ foldM (\st blk -> seq st (SHA.processSHA512Block st <$> (toSHA512Block =<< blk))) SHA.initialSHA512State blks let f :: Word64 -> Eval Value- f = pure . VWord 64 . pure . WordVal . BV 64 . toInteger- zs = finiteSeqMap (map f [w0,w1,w2,w3,w4,w5,w6,w7])+ f = pure . VWord 64 . wordVal . BV 64 . toInteger+ zs = finiteSeqMap Concrete (map f [w0,w1,w2,w3,w4,w5,w6,w7]) seq zs (pure (VSeq 8 zs))) , ("AESKeyExpand", {-# SCC "SuiteB::AESKeyExpand" #-}@@ -336,11 +324,11 @@ let toWord :: Integer -> Eval Word32 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESInfKeyExpand" =<< lookupSeqMap ss i) let fromWord :: Word32 -> Eval Value- fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger+ fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger kws <- mapM toWord [0 .. k-1] let ws = AES.keyExpansionWords k kws let len = 4*(k+7)- pure (VSeq len (finiteSeqMap (map fromWord ws))))+ pure (VSeq len (finiteSeqMap Concrete (map fromWord ws)))) , ("AESInvMixColumns", {-# SCC "SuiteB::AESInvMixColumns" #-} PFun \st ->@@ -349,10 +337,10 @@ let toWord :: Integer -> Eval Word32 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESInvMixColumns" =<< lookupSeqMap ss i) let fromWord :: Word32 -> Eval Value- fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger+ fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger ws <- mapM toWord [0,1,2,3] let ws' = AES.invMixColumns ws- pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')+ pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws') , ("AESEncRound", {-# SCC "SuiteB::AESEncRound" #-} PFun \st ->@@ -361,10 +349,10 @@ let toWord :: Integer -> Eval Word32 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESEncRound" =<< lookupSeqMap ss i) let fromWord :: Word32 -> Eval Value- fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger+ fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger ws <- mapM toWord [0,1,2,3] let ws' = AES.aesRound ws- pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')+ pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws') , ("AESEncFinalRound", {-# SCC "SuiteB::AESEncFinalRound" #-} PFun \st ->@@ -373,10 +361,10 @@ let toWord :: Integer -> Eval Word32 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESEncFinalRound" =<< lookupSeqMap ss i) let fromWord :: Word32 -> Eval Value- fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger+ fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger ws <- mapM toWord [0,1,2,3] let ws' = AES.aesFinalRound ws- pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')+ pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws') , ("AESDecRound", {-# SCC "SuiteB::AESDecRound" #-} PFun \st ->@@ -385,10 +373,10 @@ let toWord :: Integer -> Eval Word32 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESDecRound" =<< lookupSeqMap ss i) let fromWord :: Word32 -> Eval Value- fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger+ fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger ws <- mapM toWord [0,1,2,3] let ws' = AES.aesInvRound ws- pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')+ pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws') , ("AESDecFinalRound", {-# SCC "SuiteB::AESDecFinalRound" #-} PFun \st ->@@ -397,10 +385,10 @@ let toWord :: Integer -> Eval Word32 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESDecFinalRound" =<< lookupSeqMap ss i) let fromWord :: Word32 -> Eval Value- fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger+ fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger ws <- mapM toWord [0,1,2,3] let ws' = AES.aesInvFinalRound ws- pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')+ pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws') ] @@ -449,152 +437,39 @@ (toWord 14) <*> (toWord 15) --------------------------------------------------------------------------------- -sshrV :: Prim Concrete-sshrV =- PNumPoly \_n ->- PTyPoly \ix ->- PWordFun \(BV w x) ->- PFun \y ->- PPrim- do idx <- y >>= asIndex Concrete ">>$" ix >>= \case- Left idx -> pure idx- Right wv -> bvVal <$> asWordVal Concrete wv- return $ VWord w $ pure $ WordVal $ mkBv w $ signedShiftRW w x idx--logicShift :: (Integer -> Integer -> Integer -> Integer)- -- ^ The function may assume its arguments are masked.- -- It is responsible for masking its result if needed.- -> (Nat' -> TValue -> SeqMap Concrete -> Integer -> SeqMap Concrete)- -> Prim Concrete-logicShift opW opS =- PNumPoly \a ->- PTyPoly \_ix ->- PTyPoly \c ->- PFun \l ->- PFun \r ->- PPrim- do i <- r >>= \case- VInteger i -> pure i- VWord _ wval -> bvVal <$> (asWordVal Concrete =<< wval)- _ -> evalPanic "logicShift" ["not an index"]- l >>= \case- VWord w wv -> return $ VWord w $ wv >>= \case- WordVal (BV _ x) -> return $ WordVal (BV w (opW w x i))- LargeBitsVal n xs -> return $ LargeBitsVal n $ opS (Nat n) c xs i-- _ -> mkSeq a c <$> (opS a c <$> (fromSeq "logicShift" =<< l) <*> return i)---- Left shift for words.-shiftLW :: Integer -> Integer -> Integer -> Integer-shiftLW w ival by- | by < 0 = shiftRW w ival (negate by)- | by >= w = 0- | by > toInteger (maxBound :: Int) = panic "shiftLW" ["Shift amount too large", show by]- | otherwise = mask w (shiftL ival (fromInteger by))---- Right shift for words-shiftRW :: Integer -> Integer -> Integer -> Integer-shiftRW w ival by- | by < 0 = shiftLW w ival (negate by)- | by >= w = 0- | by > toInteger (maxBound :: Int) = panic "shiftRW" ["Shift amount too large", show by]- | otherwise = shiftR ival (fromInteger by)---- signed right shift for words-signedShiftRW :: Integer -> Integer -> Integer -> Integer-signedShiftRW w ival by- | by < 0 = shiftLW w ival (negate by)- | otherwise =- let by' = min w by in- if by' > toInteger (maxBound :: Int) then- panic "signedShiftRW" ["Shift amount too large", show by]- else- shiftR (signedValue w ival) (fromInteger by')--shiftLS :: Nat' -> TValue -> SeqMap Concrete -> Integer -> SeqMap Concrete-shiftLS w ety vs by- | by < 0 = shiftRS w ety vs (negate by)--shiftLS w ety vs by = IndexSeqMap $ \i ->- case w of- Nat len- | i+by < len -> lookupSeqMap vs (i+by)- | i < len -> zeroV Concrete ety- | otherwise -> evalPanic "shiftLS" ["Index out of bounds"]- Inf -> lookupSeqMap vs (i+by)--shiftRS :: Nat' -> TValue -> SeqMap Concrete -> Integer -> SeqMap Concrete-shiftRS w ety vs by- | by < 0 = shiftLS w ety vs (negate by)--shiftRS w ety vs by = IndexSeqMap $ \i ->- case w of- Nat len- | i >= by -> lookupSeqMap vs (i-by)- | i < len -> zeroV Concrete ety- | otherwise -> evalPanic "shiftLS" ["Index out of bounds"]- Inf- | i >= by -> lookupSeqMap vs (i-by)- | otherwise -> zeroV Concrete ety----- XXX integer doesn't implement rotateL, as there's no bit bound-rotateLW :: Integer -> Integer -> Integer -> Integer-rotateLW 0 i _ = i-rotateLW w i by = mask w $ (i `shiftL` b) .|. (i `shiftR` (fromInteger w - b))- where b = fromInteger (by `mod` w)--rotateLS :: Nat' -> TValue -> SeqMap Concrete -> Integer -> SeqMap Concrete-rotateLS w _ vs by = IndexSeqMap $ \i ->- case w of- Nat len -> lookupSeqMap vs ((by + i) `mod` len)- _ -> panic "Cryptol.Eval.Prim.rotateLS" [ "unexpected infinite sequence" ]---- XXX integer doesn't implement rotateR, as there's no bit bound-rotateRW :: Integer -> Integer -> Integer -> Integer-rotateRW 0 i _ = i-rotateRW w i by = mask w $ (i `shiftR` b) .|. (i `shiftL` (fromInteger w - b))- where b = fromInteger (by `mod` w)--rotateRS :: Nat' -> TValue -> SeqMap Concrete -> Integer -> SeqMap Concrete-rotateRS w _ vs by = IndexSeqMap $ \i ->- case w of- Nat len -> lookupSeqMap vs ((len - by + i) `mod` len)- _ -> panic "Cryptol.Eval.Prim.rotateRS" [ "unexpected infinite sequence" ]-- -- Sequence Primitives --------------------------------------------------------- -indexFront :: Nat' -> TValue -> SeqMap Concrete -> TValue -> BV -> Eval Value-indexFront _mblen _a vs _ix (bvVal -> ix) = lookupSeqMap vs ix--indexFront_bits :: Nat' -> TValue -> SeqMap Concrete -> TValue -> [Bool] -> Eval Value-indexFront_bits mblen a vs ix bs = indexFront mblen a vs ix =<< packWord Concrete bs--indexFront_int :: Nat' -> TValue -> SeqMap Concrete -> TValue -> Integer -> Eval Value+indexFront_int :: Nat' -> TValue -> SeqMap Concrete (GenValue Concrete) -> TValue -> Integer -> Eval Value indexFront_int _mblen _a vs _ix idx = lookupSeqMap vs idx -indexBack :: Nat' -> TValue -> SeqMap Concrete -> TValue -> BV -> Eval Value-indexBack mblen a vs ix (bvVal -> idx) = indexBack_int mblen a vs ix idx--indexBack_bits :: Nat' -> TValue -> SeqMap Concrete -> TValue -> [Bool] -> Eval Value-indexBack_bits mblen a vs ix bs = indexBack mblen a vs ix =<< packWord Concrete bs+indexFront_segs :: Nat' -> TValue -> SeqMap Concrete (GenValue Concrete) -> TValue -> Integer -> [IndexSegment Concrete] -> Eval Value+indexFront_segs _mblen _a vs _ix idx_bits segs = lookupSeqMap vs $! packSegments idx_bits segs -indexBack_int :: Nat' -> TValue -> SeqMap Concrete -> TValue -> Integer -> Eval Value-indexBack_int mblen _a vs _ix idx =- case mblen of- Nat len -> lookupSeqMap vs (len - idx - 1)- Inf -> evalPanic "indexBack" ["unexpected infinite sequence"]+packSegments :: Integer -> [IndexSegment Concrete] -> Integer+packSegments = loop 0+ where+ loop !val !n segs =+ case segs of+ [] -> val+ [WordIndexSegment (BV _ x)] -> val + x+ WordIndexSegment (BV xlen x) : bs ->+ let n' = n - xlen+ in loop (val + (x*2^n')) n' bs+ BitIndexSegment True : bs ->+ let n' = n - 1+ in loop (val + 2^n') n' bs+ BitIndexSegment False : bs ->+ let n' = n - 1+ in loop val n' bs updateFront :: Nat' {- ^ length of the sequence -} -> TValue {- ^ type of values in the sequence -} ->- SeqMap Concrete {- ^ sequence to update -} ->+ SeqMap Concrete (GenValue Concrete) {- ^ sequence to update -} -> Either Integer (WordValue Concrete) {- ^ index -} -> Eval Value {- ^ new value at index -} ->- Eval (SeqMap Concrete)+ Eval (SeqMap Concrete (GenValue Concrete)) updateFront _len _eltTy vs (Left idx) val = do return $ updateSeqMap vs idx val @@ -619,10 +494,10 @@ updateBack :: Nat' {- ^ length of the sequence -} -> TValue {- ^ type of values in the sequence -} ->- SeqMap Concrete {- ^ sequence to update -} ->+ SeqMap Concrete (GenValue Concrete) {- ^ sequence to update -} -> Either Integer (WordValue Concrete) {- ^ index -} -> Eval Value {- ^ new value at index -} ->- Eval (SeqMap Concrete)+ Eval (SeqMap Concrete (GenValue Concrete)) updateBack Inf _eltTy _vs _w _val = evalPanic "Unexpected infinite sequence in updateEnd" [] updateBack (Nat n) _eltTy vs (Left idx) val = do
src/Cryptol/Eval/Env.hs view
@@ -6,8 +6,6 @@ -- Stability : provisional -- Portability : portable -{-# LANGUAGE Safe #-}- {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE DeriveAnyClass #-}
src/Cryptol/Eval/Generic.hs view
@@ -19,25 +19,28 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE BangPatterns #-}+ {-# OPTIONS_GHC -fno-warn-orphans #-} module Cryptol.Eval.Generic where import qualified Control.Exception as X+import Control.Monad(join) import Control.Monad.IO.Class (MonadIO(..))-import Control.Monad (join, unless) import System.Random.TF.Gen (seedTFGen) -import Data.Bits (testBit, (.&.), shiftR)+import Data.Bits ((.&.), shiftR) import Data.Maybe (fromMaybe) import qualified Data.Map.Strict as Map import Data.Map(Map) import Data.Ratio ((%)) import Cryptol.TypeCheck.AST-import Cryptol.TypeCheck.Solver.InfNat (Nat'(..),nMul,widthInteger)+import Cryptol.TypeCheck.Solver.InfNat (Nat'(..),nMul) import Cryptol.Backend import Cryptol.Backend.Concrete (Concrete(..)) import Cryptol.Backend.Monad( Eval, evalPanic, EvalError(..), Unsupported(..) )+import Cryptol.Backend.SeqMap+import Cryptol.Backend.WordValue import Cryptol.Testing.Random( randomValue ) import Cryptol.Eval.Prims@@ -63,7 +66,7 @@ | m == 0 -> evalPanic "mkLit" ["0 modulus not allowed"] | otherwise -> VInteger <$> integerLit sym (i `mod` m) TVFloat e p -> VFloat <$> fpLit sym e p (fromInteger i)- TVSeq w TVBit -> pure $ word sym w i+ TVSeq w TVBit -> word sym w i TVRational -> VRational <$> (intToRational sym =<< integerLit sym i) _ -> evalPanic "Cryptol.Eval.Prim.evalConst" [ "Invalid type for number" ]@@ -217,14 +220,14 @@ lw <- fromVWord sym "ringLeft" l rw <- fromVWord sym "ringRight" r stk <- sGetCallStack sym- return $ VWord w (WordVal <$> (sWithCallStack sym stk (opw w lw rw)))- | otherwise -> VSeq w <$> (join (zipSeqMap sym (loop a) <$>+ VWord w . wordVal <$> (sWithCallStack sym stk (opw w lw rw))+ | otherwise -> VSeq w <$> (join (zipSeqMap sym (loop a) (Nat w) <$> (fromSeq "ringBinary left" l) <*> (fromSeq "ringBinary right" r))) TVStream a -> -- streams- VStream <$> (join (zipSeqMap sym (loop a) <$>+ VStream <$> (join (zipSeqMap sym (loop a) Inf <$> (fromSeq "ringBinary left" l) <*> (fromSeq "ringBinary right" r))) @@ -303,11 +306,11 @@ | isTBit a -> do wx <- fromVWord sym "ringUnary" v stk <- sGetCallStack sym- return $ VWord w (WordVal <$> sWithCallStack sym stk (opw w wx))- | otherwise -> VSeq w <$> (mapSeqMap sym (loop a) =<< fromSeq "ringUnary" v)+ VWord w . wordVal <$> sWithCallStack sym stk (opw w wx)+ | otherwise -> VSeq w <$> (mapSeqMap sym (loop a) (Nat w) =<< fromSeq "ringUnary" v) TVStream a ->- VStream <$> (mapSeqMap sym (loop a) =<< fromSeq "ringUnary" v)+ VStream <$> (mapSeqMap sym (loop a) Inf =<< fromSeq "ringUnary" v) -- functions TVFun _ ety ->@@ -372,14 +375,14 @@ -- words and finite sequences | isTBit a -> do stk <- sGetCallStack sym- pure $ VWord w $ (WordVal <$> sWithCallStack sym stk (opw w))+ VWord w . wordVal <$> sWithCallStack sym stk (opw w) | otherwise -> do v <- sDelay sym (loop a)- pure $ VSeq w $ IndexSeqMap \_i -> v+ pure $ VSeq w $ indexSeqMap \_i -> v TVStream a -> do v <- sDelay sym (loop a)- pure $ VStream $ IndexSeqMap \_i -> v+ pure $ VStream $ indexSeqMap \_i -> v TVFun _ b -> do v <- sDelay sym (loop b)@@ -420,7 +423,7 @@ do wl <- fromVWord sym "integralBinary left" l wr <- fromVWord sym "integralBinary right" r stk <- sGetCallStack sym- return $ VWord w (WordVal <$> sWithCallStack sym stk (opw w wl wr))+ VWord w . wordVal <$> sWithCallStack sym stk (opw w wl wr) _ -> evalPanic "integralBinary" [show ty ++ " not int class `Integral`"] @@ -509,7 +512,7 @@ intV sym onei aty | n > 0 ->- do ebits <- enumerateIntBits' sym n ei+ do (_,ebits) <- enumerateIntBits' sym n ei computeExponent sym aty a ebits | otherwise -> raiseError sym NegativeExponent@@ -517,7 +520,7 @@ Nothing -> liftIO (X.throw (UnsupportedSymbolicOp "integer exponentiation")) TVSeq _w el | isTBit el ->- do ebits <- enumerateWordValue sym =<< fromWordVal "(^^)" e+ do ebits <- enumerateWordValue sym (fromWordVal "(^^)" e) computeExponent sym aty a ebits _ -> evalPanic "expV" [show ety ++ " not int class `Integral`"]@@ -695,7 +698,7 @@ lg2V sym = PFinPoly \w -> PWordFun \x ->- PVal (VWord w (WordVal <$> wordLg2 sym x))+ PPrim (VWord w . wordVal <$> wordLg2 sym x) {-# SPECIALIZE sdivV :: Concrete -> Prim Concrete #-} sdivV :: Backend sym => sym -> Prim sym@@ -703,7 +706,7 @@ PFinPoly \w -> PWordFun \x -> PWordFun \y ->- PVal (VWord w (WordVal <$> wordSignedDiv sym x y))+ PPrim (VWord w . wordVal <$> wordSignedDiv sym x y) {-# SPECIALIZE smodV :: Concrete -> Prim Concrete #-} smodV :: Backend sym => sym -> Prim sym@@ -711,8 +714,15 @@ PFinPoly \w -> PWordFun \x -> PWordFun \y ->- PVal (VWord w (WordVal <$> wordSignedMod sym x y))+ PPrim (VWord w . wordVal <$> wordSignedMod sym x y) +{-# SPECIALIZE toSignedIntegerV :: Concrete -> Prim Concrete #-}+toSignedIntegerV :: Backend sym => sym -> Prim sym+toSignedIntegerV sym =+ PFinPoly \_w ->+ PWordFun \x ->+ PPrim (VInteger <$> wordToSignedInt sym x)+ -- Cmp ------------------------------------------------------------------------- {-# SPECIALIZE cmpValue ::@@ -915,14 +925,14 @@ -- sequences TVSeq w ety- | isTBit ety -> pure $ word sym w 0+ | isTBit ety -> word sym w 0 | otherwise -> do z <- sDelay sym (zeroV sym ety)- pure $ VSeq w (IndexSeqMap \_i -> z)+ pure $ VSeq w (indexSeqMap \_i -> z) TVStream ety -> do z <- sDelay sym (zeroV sym ety)- pure $ VStream (IndexSeqMap \_i -> z)+ pure $ VStream (indexSeqMap \_i -> z) -- functions TVFun _ bty ->@@ -943,52 +953,13 @@ TVNewtype {} -> evalPanic "zeroV" [ "Newtype not in `Zero`" ] --- | otherwise = evalPanic "zeroV" ["invalid type for zero"] -{-# INLINE joinWordVal #-}-joinWordVal :: Backend sym => sym -> WordValue sym -> WordValue sym -> SEval sym (WordValue sym)-joinWordVal sym (WordVal w1) (WordVal w2)- | wordLen sym w1 + wordLen sym w2 < largeBitSize- = WordVal <$> joinWord sym w1 w2-joinWordVal sym w1 w2- = pure $ LargeBitsVal (n1+n2) (concatSeqMap n1 (asBitsMap sym w1) (asBitsMap sym w2))- where n1 = wordValueSize sym w1- n2 = wordValueSize sym w2---{-# SPECIALIZE joinWords ::- Concrete ->- Integer ->- Integer ->- SeqMap Concrete ->- SEval Concrete (GenValue Concrete)- #-}-joinWords :: forall sym.- Backend sym =>- sym ->- Integer ->- Integer ->- SeqMap sym ->- SEval sym (GenValue sym)-joinWords sym nParts nEach xs =- loop (WordVal <$> wordLit sym 0 0) (enumerateSeqMap nParts xs)-- where- loop :: SEval sym (WordValue sym) -> [SEval sym (GenValue sym)] -> SEval sym (GenValue sym)- loop !wv [] =- VWord (nParts * nEach) <$> sDelay sym wv- loop !wv (w : ws) =- w >>= \case- VWord _ w' ->- loop (join (joinWordVal sym <$> wv <*> w')) ws- _ -> evalPanic "joinWords: expected word value" []- {-# SPECIALIZE joinSeq :: Concrete -> Nat' -> Integer -> TValue ->- SeqMap Concrete ->+ SEval Concrete (SeqMap Concrete (GenValue Concrete)) -> SEval Concrete (GenValue Concrete) #-} joinSeq ::@@ -997,35 +968,32 @@ Nat' -> Integer -> TValue ->- SeqMap sym ->+ SEval sym (SeqMap sym (GenValue sym)) -> SEval sym (GenValue sym) -- Special case for 0 length inner sequences.-joinSeq sym _parts 0 a _xs+joinSeq sym _parts 0 a _val = zeroV sym (TVSeq 0 a) -- finite sequence of words-joinSeq sym (Nat parts) each TVBit xs- | parts * each < largeBitSize- = joinWords sym parts each xs- | otherwise- = do let zs = IndexSeqMap $ \i ->- do let (q,r) = divMod i each- ys <- fromWordVal "join seq" =<< lookupSeqMap xs q- VBit <$> indexWordValue sym ys r- return $ VWord (parts * each) $ pure $ LargeBitsVal (parts * each) zs+joinSeq sym (Nat parts) each TVBit val+ = do w <- delayWordValue sym (parts*each)+ (joinWords sym parts each . fmap (fromWordVal "joinV") =<< val)+ pure (VWord (parts*each) w) -- infinite sequence of words-joinSeq sym Inf each TVBit xs- = return $ VStream $ IndexSeqMap $ \i ->+joinSeq sym Inf each TVBit val+ = return $ VStream $ indexSeqMap $ \i -> do let (q,r) = divMod i each- ys <- fromWordVal "join seq" =<< lookupSeqMap xs q+ xs <- val+ ys <- fromWordVal "join seq" <$> lookupSeqMap xs q VBit <$> indexWordValue sym ys r -- finite or infinite sequence of non-words-joinSeq _sym parts each _a xs- = return $ vSeq $ IndexSeqMap $ \i -> do+joinSeq _sym parts each _a val+ = return $ vSeq $ indexSeqMap $ \i -> do let (q,r) = divMod i each+ xs <- val ys <- fromSeq "join seq" =<< lookupSeqMap xs q lookupSeqMap ys r where@@ -1044,146 +1012,115 @@ Nat' -> Integer -> TValue ->- GenValue sym ->+ SEval sym (GenValue sym) -> SEval sym (GenValue sym)-joinV sym parts each a val = joinSeq sym parts each a =<< fromSeq "joinV" val---{-# INLINE splitWordVal #-}--splitWordVal ::- Backend sym =>- sym ->- Integer ->- Integer ->- WordValue sym ->- SEval sym (WordValue sym, WordValue sym)-splitWordVal sym leftWidth rightWidth (WordVal w) =- do (lw, rw) <- splitWord sym leftWidth rightWidth w- pure (WordVal lw, WordVal rw)-splitWordVal _ leftWidth rightWidth (LargeBitsVal _n xs) =- let (lxs, rxs) = splitSeqMap leftWidth xs- in pure (LargeBitsVal leftWidth lxs, LargeBitsVal rightWidth rxs)+joinV sym parts each a val =+ do xs <- sDelay sym (fromSeq "joinV" =<< val)+ joinSeq sym parts each a xs -{-# INLINE splitAtV #-}-splitAtV ::+{-# INLINE takeV #-}+takeV :: Backend sym => sym -> Nat' -> Nat' -> TValue ->- GenValue sym ->+ SEval sym (GenValue sym) -> SEval sym (GenValue sym)-splitAtV sym front back a val =- case back of-- Nat rightWidth | aBit -> do- ws <- sDelay sym (splitWordVal sym leftWidth rightWidth =<< fromWordVal "splitAtV" val)- return $ VTuple- [ VWord leftWidth . pure . fst <$> ws- , VWord rightWidth . pure . snd <$> ws- ]-- Inf | aBit -> do- vs <- sDelay sym (fromSeq "splitAtV" val)- ls <- sDelay sym (fst . splitSeqMap leftWidth <$> vs)- rs <- sDelay sym (snd . splitSeqMap leftWidth <$> vs)- return $ VTuple [ return $ VWord leftWidth (LargeBitsVal leftWidth <$> ls)- , VStream <$> rs- ]-- _ -> do- vs <- sDelay sym (fromSeq "splitAtV" val)- ls <- sDelay sym (fst . splitSeqMap leftWidth <$> vs)- rs <- sDelay sym (snd . splitSeqMap leftWidth <$> vs)- return $ VTuple [ VSeq leftWidth <$> ls- , mkSeq back a <$> rs- ]-- where- aBit = isTBit a-- leftWidth = case front of- Nat n -> n- _ -> evalPanic "splitAtV" ["invalid `front` len"]+takeV sym front back a val =+ case front of+ Inf -> val+ Nat front' ->+ case back of+ Nat back' | isTBit a ->+ do w <- delayWordValue sym front' (takeWordVal sym front' back' =<< (fromWordVal "takeV" <$> val))+ pure (VWord front' w) + Inf | isTBit a ->+ do w <- delayWordValue sym front' (bitmapWordVal sym front' . fmap fromVBit =<< (fromSeq "takeV" =<< val))+ pure (VWord front' w) -{-# INLINE extractWordVal #-}+ _ ->+ do xs <- delaySeqMap sym (fromSeq "takeV" =<< val)+ pure (VSeq front' xs) --- | Extract a subsequence of bits from a @WordValue@.--- The first integer argument is the number of bits in the--- resulting word. The second integer argument is the--- number of less-significant digits to discard. Stated another--- way, the operation `extractWordVal n i w` is equivalent to--- first shifting `w` right by `i` bits, and then truncating to--- `n` bits.-extractWordVal ::+{-# INLINE dropV #-}+dropV :: Backend sym => sym -> Integer ->- Integer ->- WordValue sym ->- SEval sym (WordValue sym)-extractWordVal sym len start (WordVal w) =- WordVal <$> extractWord sym len start w-extractWordVal _ len start (LargeBitsVal n xs) =- let xs' = dropSeqMap (n - start - len) xs- in pure $ LargeBitsVal len xs'+ Nat' ->+ TValue ->+ SEval sym (GenValue sym) ->+ SEval sym (GenValue sym)+dropV sym front back a val =+ case back of+ Nat back' | isTBit a ->+ do w <- delayWordValue sym back' (dropWordVal sym front back' =<< (fromWordVal "dropV" <$> val))+ pure (VWord back' w) -{-# INLINE ecSplitV #-}+ _ ->+ do xs <- delaySeqMap sym (dropSeqMap front <$> (fromSeq "dropV" =<< val))+ mkSeq sym back a xs ++{-# INLINE splitV #-}+ -- | Split implementation.-ecSplitV :: Backend sym => sym -> Prim sym-ecSplitV sym =- PNumPoly \parts ->- PNumPoly \each ->- PTyPoly \a ->- PFun \val ->- PPrim+splitV :: Backend sym =>+ sym ->+ Nat' ->+ Integer ->+ TValue ->+ SEval sym (GenValue sym) ->+ SEval sym (GenValue sym)+splitV sym parts each a val = case (parts, each) of- (Nat p, Nat e) | isTBit a -> do- ~(VWord _ val') <- val- return $ VSeq p $ IndexSeqMap $ \i ->- pure $ VWord e (extractWordVal sym e ((p-i-1)*e) =<< val')- (Inf, Nat e) | isTBit a -> do- val' <- sDelay sym (fromSeq "ecSplitV" =<< val)- return $ VStream $ IndexSeqMap $ \i ->- return $ VWord e $ return $ LargeBitsVal e $ IndexSeqMap $ \j ->+ (Nat p, e) | isTBit a -> do+ val' <- sDelay sym (fromWordVal "splitV" <$> val)+ return $ VSeq p $ indexSeqMap $ \i ->+ VWord e <$> (extractWordVal sym e ((p-i-1)*e) =<< val')+ (Inf, e) | isTBit a -> do+ val' <- sDelay sym (fromSeq "splitV" =<< val)+ return $ VStream $ indexSeqMap $ \i ->+ VWord e <$> bitmapWordVal sym e (indexSeqMap $ \j -> let idx = i*e + toInteger j in idx `seq` do xs <- val'- lookupSeqMap xs idx- (Nat p, Nat e) -> do- val' <- sDelay sym (fromSeq "ecSplitV" =<< val)- return $ VSeq p $ IndexSeqMap $ \i ->- return $ VSeq e $ IndexSeqMap $ \j -> do+ fromVBit <$> lookupSeqMap xs idx)+ (Nat p, e) -> do+ val' <- sDelay sym (fromSeq "splitV" =<< val)+ return $ VSeq p $ indexSeqMap $ \i ->+ return $ VSeq e $ indexSeqMap $ \j -> do xs <- val' lookupSeqMap xs (e * i + j)- (Inf , Nat e) -> do- val' <- sDelay sym (fromSeq "ecSplitV" =<< val)- return $ VStream $ IndexSeqMap $ \i ->- return $ VSeq e $ IndexSeqMap $ \j -> do+ (Inf , e) -> do+ val' <- sDelay sym (fromSeq "splitV" =<< val)+ return $ VStream $ indexSeqMap $ \i ->+ return $ VSeq e $ indexSeqMap $ \j -> do xs <- val' lookupSeqMap xs (e * i + j)- _ -> evalPanic "splitV" ["invalid type arguments to split"] + {-# INLINE reverseV #-} reverseV :: forall sym. Backend sym => sym ->- GenValue sym ->+ Integer ->+ TValue ->+ SEval sym (GenValue sym) -> SEval sym (GenValue sym)-reverseV _ (VSeq n xs) =- return $ VSeq n $ reverseSeqMap n xs-reverseV sym (VWord n x) = return (VWord n (revword <$> x))- where- revword wv =- let m = wordValueSize sym wv in- LargeBitsVal m $ reverseSeqMap m $ asBitsMap sym wv-reverseV _ _ =- evalPanic "reverseV" ["Not a finite sequence"] +reverseV sym n TVBit val =+ do w <- delayWordValue sym n (reverseWordVal sym . fromWordVal "reverseV" =<< val)+ pure (VWord n w)++reverseV sym n _a val =+ do xs <- delaySeqMap sym (reverseSeqMap n <$> (fromSeq "reverseV" =<< val))+ pure (VSeq n xs)++ {-# INLINE transposeV #-} transposeV ::@@ -1196,28 +1133,28 @@ SEval sym (GenValue sym) transposeV sym a b c xs | isTBit c, Nat na <- a = -- Fin a => [a][b]Bit -> [b][a]Bit- return $ bseq $ IndexSeqMap $ \bi ->- return $ VWord na $ return $ LargeBitsVal na $ IndexSeqMap $ \ai ->+ return $ bseq $ indexSeqMap $ \bi ->+ VWord na <$> bitmapWordVal sym na (indexSeqMap $ \ai -> do xs' <- fromSeq "transposeV" xs ys <- lookupSeqMap xs' ai case ys of- VStream ys' -> lookupSeqMap ys' bi- VWord _ wv -> VBit <$> (flip (indexWordValue sym) bi =<< wv)- _ -> evalPanic "transpose" ["expected sequence of bits"]+ VStream ys' -> fromVBit <$> lookupSeqMap ys' bi+ VWord _ wv -> indexWordValue sym wv bi+ _ -> evalPanic "transpose" ["expected sequence of bits"]) | isTBit c, Inf <- a = -- [inf][b]Bit -> [b][inf]Bit- return $ bseq $ IndexSeqMap $ \bi ->- return $ VStream $ IndexSeqMap $ \ai ->+ return $ bseq $ indexSeqMap $ \bi ->+ return $ VStream $ indexSeqMap $ \ai -> do xs' <- fromSeq "transposeV" xs ys <- lookupSeqMap xs' ai case ys of VStream ys' -> lookupSeqMap ys' bi- VWord _ wv -> VBit <$> (flip (indexWordValue sym) bi =<< wv)+ VWord _ wv -> VBit <$> indexWordValue sym wv bi _ -> evalPanic "transpose" ["expected sequence of bits"] | otherwise = -- [a][b]c -> [b][a]c- return $ bseq $ IndexSeqMap $ \bi ->- return $ aseq $ IndexSeqMap $ \ai -> do+ return $ bseq $ indexSeqMap $ \bi ->+ return $ aseq $ indexSeqMap $ \ai -> do xs' <- fromSeq "transposeV 1" xs ys <- fromSeq "transposeV 2" =<< lookupSeqMap xs' ai z <- lookupSeqMap ys bi@@ -1239,54 +1176,52 @@ ccatV :: Backend sym => sym ->- Nat' ->+ Integer -> Nat' -> TValue ->- (GenValue sym) ->- (GenValue sym) ->+ SEval sym (GenValue sym) ->+ SEval sym (GenValue sym) -> SEval sym (GenValue sym) -ccatV sym _front _back _elty (VWord m l) (VWord n r) =- return $ VWord (m+n) (join (joinWordVal sym <$> l <*> r))+-- Finite bitvectors+ccatV sym front (Nat back) TVBit l r =+ do ml <- isReady sym l+ mr <- isReady sym r+ case (ml, mr) of+ (Just l', Just r') ->+ VWord (front+back) <$>+ joinWordVal sym (fromWordVal "ccatV left" l') (fromWordVal "ccatV right" r')+ _ ->+ VWord (front+back) <$> delayWordValue sym (front+back)+ (do l' <- fromWordVal "ccatV left" <$> l+ r' <- fromWordVal "ccatV right" <$> r+ joinWordVal sym l' r') -ccatV sym _front _back _elty (VWord m l) (VStream r) = do- l' <- sDelay sym l- return $ VStream $ IndexSeqMap $ \i ->- if i < m then- VBit <$> (flip (indexWordValue sym) i =<< l')- else- lookupSeqMap r (i-m)+-- Infinite bitstream+ccatV sym front Inf TVBit l r =+ do l'' <- sDelay sym (asBitsMap sym . fromWordVal "ccatV left" <$> l)+ r'' <- sDelay sym (fromSeq "ccatV right" =<< r)+ pure $ VStream $ indexSeqMap $ \i ->+ if i < front then do+ ls <- l''+ VBit <$> lookupSeqMap ls i+ else do+ rs <- r''+ lookupSeqMap rs (i-front) -ccatV sym front back elty l r = do- l'' <- sDelay sym (fromSeq "ccatV left" l)- r'' <- sDelay sym (fromSeq "ccatV right" r)- let Nat n = front- mkSeq (evalTF TCAdd [front,back]) elty <$> return (IndexSeqMap $ \i ->- if i < n then do- ls <- l''- lookupSeqMap ls i- else do- rs <- r''- lookupSeqMap rs (i-n))+-- streams/sequences of nonbits+ccatV sym front back elty l r =+ do l'' <- sDelay sym (fromSeq "ccatV left" =<< l)+ r'' <- sDelay sym (fromSeq "ccatV right" =<< r)+ mkSeq sym (evalTF TCAdd [Nat front,back]) elty $ indexSeqMap $ \i ->+ if i < front then do+ ls <- l''+ lookupSeqMap ls i+ else do+ rs <- r''+ lookupSeqMap rs (i-front) -{-# INLINE wordValLogicOp #-} -wordValLogicOp ::- Backend sym =>- sym ->- (SBit sym -> SBit sym -> SEval sym (SBit sym)) ->- (SWord sym -> SWord sym -> SEval sym (SWord sym)) ->- WordValue sym ->- WordValue sym ->- SEval sym (WordValue sym)-wordValLogicOp _sym _ wop (WordVal w1) (WordVal w2) = WordVal <$> wop w1 w2--wordValLogicOp sym bop _ w1 w2 = LargeBitsVal (wordValueSize sym w1) <$> zs- where zs = memoMap sym $ IndexSeqMap $ \i -> join (op <$> (lookupSeqMap xs i) <*> (lookupSeqMap ys i))- xs = asBitsMap sym w1- ys = asBitsMap sym w2- op x y = VBit <$> (bop (fromVBit x) (fromVBit y))- {-# SPECIALIZE logicBinary :: Concrete -> (SBit Concrete -> SBit Concrete -> SEval Concrete (SBit Concrete)) ->@@ -1325,20 +1260,19 @@ TVSeq w aty -- words | isTBit aty- -> do v <- sDelay sym $ join- (wordValLogicOp sym opb opw <$>- fromWordVal "logicBinary l" l <*>- fromWordVal "logicBinary r" r)- return $ VWord w v+ -> VWord w <$> delayWordValue sym w+ (wordValLogicOp sym opb opw+ (fromWordVal "logicBinary l" l)+ (fromWordVal "logicBinary r" r)) -- finite sequences | otherwise -> VSeq w <$>- (join (zipSeqMap sym (loop aty) <$>+ (join (zipSeqMap sym (loop aty) (Nat w) <$> (fromSeq "logicBinary left" l) <*> (fromSeq "logicBinary right" r))) TVStream aty ->- VStream <$> (join (zipSeqMap sym (loop aty) <$>+ VStream <$> (join (zipSeqMap sym (loop aty) Inf <$> (fromSeq "logicBinary left" l) <*> (fromSeq "logicBinary right" r))) @@ -1362,18 +1296,6 @@ TVNewtype {} -> evalPanic "logicBinary" [ "Newtype not in `Logic`" ] -{-# INLINE wordValUnaryOp #-}-wordValUnaryOp ::- Backend sym =>- sym ->- (SBit sym -> SEval sym (SBit sym)) ->- (SWord sym -> SEval sym (SWord sym)) ->- WordValue sym ->- SEval sym (WordValue sym)-wordValUnaryOp _ _ wop (WordVal w) = WordVal <$> (wop w)-wordValUnaryOp sym bop _ (LargeBitsVal n xs) = LargeBitsVal n <$> mapSeqMap sym f xs- where f x = VBit <$> (bop (fromVBit x))- {-# SPECIALIZE logicUnary :: Concrete -> (SBit Concrete -> SEval Concrete (SBit Concrete)) ->@@ -1405,16 +1327,15 @@ TVSeq w ety -- words | isTBit ety- -> do v <- sDelay sym (wordValUnaryOp sym opb opw =<< fromWordVal "logicUnary" val)- return $ VWord w v+ -> VWord w <$> delayWordValue sym w (wordValUnaryOp sym opb opw (fromWordVal "logicUnary" val)) -- finite sequences | otherwise- -> VSeq w <$> (mapSeqMap sym (loop ety) =<< fromSeq "logicUnary" val)+ -> VSeq w <$> (mapSeqMap sym (loop ety) (Nat w) =<< fromSeq "logicUnary" val) -- streams TVStream ety ->- VStream <$> (mapSeqMap sym (loop ety) =<< fromSeq "logicUnary" val)+ VStream <$> (mapSeqMap sym (loop ety) Inf =<< fromSeq "logicUnary" val) TVTuple etys -> do as <- mapM (sDelay sym) (fromVTuple val)@@ -1433,32 +1354,7 @@ TVNewtype {} -> evalPanic "logicUnary" [ "Newtype not in `Logic`" ] -{-# SPECIALIZE bitsValueLessThan ::- Concrete ->- Integer ->- [SBit Concrete] ->- Integer ->- SEval Concrete (SBit Concrete)- #-}-bitsValueLessThan ::- Backend sym =>- sym ->- Integer {- ^ bit-width -} ->- [SBit sym] {- ^ big-endian list of index bits -} ->- Integer {- ^ Upper bound to test against -} ->- SEval sym (SBit sym)-bitsValueLessThan sym _w [] _n = pure $ bitLit sym False-bitsValueLessThan sym w (b:bs) n- | nbit =- do notb <- bitComplement sym b- bitOr sym notb =<< bitsValueLessThan sym (w-1) bs n- | otherwise =- do notb <- bitComplement sym b- bitAnd sym notb =<< bitsValueLessThan sym (w-1) bs n- where- nbit = testBit n (fromInteger (w-1)) - {-# INLINE assertIndexInBounds #-} assertIndexInBounds :: Backend sym =>@@ -1486,30 +1382,8 @@ -- Can't index out of bounds for a sequence that is -- longer than the expressible index values-assertIndexInBounds sym (Nat n) (Right idx)- | n >= 2^(wordValueSize sym idx)- = return ()---- If the index is concrete, test it directly-assertIndexInBounds sym (Nat n) (Right (WordVal idx))- | Just (_w,i) <- wordAsLit sym idx- = unless (i < n) (raiseError sym (InvalidIndex (Just i)))---- If the index is a packed word, test that it--- is less than the concrete value of n, which--- fits into w bits because of the above test.-assertIndexInBounds sym (Nat n) (Right (WordVal idx)) =- do n' <- wordLit sym (wordLen sym idx) n- p <- wordLessThan sym idx n'- assertSideCondition sym p (InvalidIndex Nothing)---- If the index is an unpacked word, force all the bits--- and compute the unsigned less-than test directly.-assertIndexInBounds sym (Nat n) (Right (LargeBitsVal w bits)) =- do bitsList <- traverse (fromVBit <$>) (enumerateSeqMap w bits)- p <- bitsValueLessThan sym w bitsList n- assertSideCondition sym p (InvalidIndex Nothing)-+assertIndexInBounds sym (Nat n) (Right idx) =+ assertWordValueInBounds sym n idx -- | Indexing operations. @@ -1517,11 +1391,11 @@ indexPrim :: Backend sym => sym ->- (Nat' -> TValue -> SeqMap sym -> TValue -> SInteger sym -> SEval sym (GenValue sym)) ->- (Nat' -> TValue -> SeqMap sym -> TValue -> [SBit sym] -> SEval sym (GenValue sym)) ->- (Nat' -> TValue -> SeqMap sym -> TValue -> SWord sym -> SEval sym (GenValue sym)) ->+ IndexDirection ->+ (Nat' -> TValue -> SeqMap sym (GenValue sym) -> TValue -> SInteger sym -> SEval sym (GenValue sym)) ->+ (Nat' -> TValue -> SeqMap sym (GenValue sym) -> TValue -> Integer -> [IndexSegment sym] -> SEval sym (GenValue sym)) -> Prim sym-indexPrim sym int_op bits_op word_op =+indexPrim sym dir int_op word_op = PNumPoly \len -> PTyPoly \eltTy -> PTyPoly \ix ->@@ -1529,16 +1403,19 @@ PFun \idx -> PPrim do vs <- xs >>= \case- VWord _ w -> w >>= \w' -> return $ IndexSeqMap (\i -> VBit <$> indexWordValue sym w' i)+ VWord _ w -> return $ indexSeqMap (\i -> VBit <$> indexWordValue sym w i) VSeq _ vs -> return vs VStream vs -> return vs _ -> evalPanic "Expected sequence value" ["indexPrim"]- idx' <- asIndex sym "index" ix =<< idx+ let vs' = case (len, dir) of+ (_ , IndexForward) -> vs+ (Nat n, IndexBackward) -> reverseSeqMap n vs+ (Inf , IndexBackward) -> evalPanic "Expected finite sequence" ["!"]+ idx' <- asIndex sym "index" ix <$> idx assertIndexInBounds sym len idx' case idx' of- Left i -> int_op len eltTy vs ix i- Right (WordVal w') -> word_op len eltTy vs ix w'- Right (LargeBitsVal m bs) -> bits_op len eltTy vs ix =<< traverse (fromVBit <$>) (enumerateSeqMap m bs)+ Left i -> int_op len eltTy vs' ix i+ Right w -> word_op len eltTy vs' ix (wordValueSize sym w) =<< enumerateIndexSegments sym w {-# INLINE updatePrim #-} @@ -1546,7 +1423,7 @@ Backend sym => sym -> (Nat' -> TValue -> WordValue sym -> Either (SInteger sym) (WordValue sym) -> SEval sym (GenValue sym) -> SEval sym (WordValue sym)) ->- (Nat' -> TValue -> SeqMap sym -> Either (SInteger sym) (WordValue sym) -> SEval sym (GenValue sym) -> SEval sym (SeqMap sym)) ->+ (Nat' -> TValue -> SeqMap sym (GenValue sym) -> Either (SInteger sym) (WordValue sym) -> SEval sym (GenValue sym) -> SEval sym (SeqMap sym (GenValue sym))) -> Prim sym updatePrim sym updateWord updateSeq = PNumPoly \len ->@@ -1556,17 +1433,17 @@ PFun \idx -> PFun \val -> PPrim- do idx' <- asIndex sym "update" ix =<< idx+ do idx' <- asIndex sym "update" ix <$> idx assertIndexInBounds sym len idx'- xs >>= \case- VWord l w -> do w' <- sDelay sym w- return $ VWord l (w' >>= \w'' -> updateWord len eltTy w'' idx' val)- VSeq l vs -> VSeq l <$> updateSeq len eltTy vs idx' val- VStream vs -> VStream <$> updateSeq len eltTy vs idx' val- _ -> evalPanic "Expected sequence value" ["updatePrim"]+ case (len, eltTy) of+ (Nat n, TVBit) -> VWord n <$> delayWordValue sym n+ (do w <- fromWordVal "updatePrim" <$> xs; updateWord len eltTy w idx' val)+ (Nat n, _ ) -> VSeq n <$> delaySeqMap sym+ (do vs <- fromSeq "updatePrim" =<< xs; updateSeq len eltTy vs idx' val)+ (Inf , _ ) -> VStream <$> delaySeqMap sym+ (do vs <- fromSeq "updatePrim" =<< xs; updateSeq len eltTy vs idx' val) {-# INLINE fromToV #-}- -- @[ 0 .. 10 ]@ fromToV :: Backend sym => sym -> Prim sym fromToV sym =@@ -1578,26 +1455,10 @@ case (first, lst) of (Nat first', Nat lst') -> let len = 1 + (lst' - first')- in VSeq len $ IndexSeqMap $ \i -> f (first' + i)+ in VSeq len $ indexSeqMap $ \i -> f (first' + i) _ -> evalPanic "fromToV" ["invalid arguments"] -{-# INLINE fromToLessThanV #-}---- @[ 0 .. <10 ]@-fromToLessThanV :: Backend sym => sym -> Prim sym-fromToLessThanV sym =- PFinPoly \first ->- PNumPoly \bound ->- PTyPoly \ty ->- PVal- let !f = mkLit sym ty- ss = IndexSeqMap $ \i -> f (first + i)- in case bound of- Inf -> VStream ss- Nat bound' -> VSeq (bound' - first) ss- {-# INLINE fromThenToV #-}- -- @[ 0, 1 .. 10 ]@ fromThenToV :: Backend sym => sym -> Prim sym fromThenToV sym =@@ -1611,9 +1472,78 @@ 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 VSeq len' $ indexSeqMap $ \i -> f (first' + i*diff) _ -> evalPanic "fromThenToV" ["invalid arguments"] +{-# INLINE fromToLessThanV #-}+-- @[ 0 .. <10 ]@+fromToLessThanV :: Backend sym => sym -> Prim sym+fromToLessThanV sym =+ PFinPoly \first ->+ PNumPoly \bound ->+ PTyPoly \ty ->+ PVal+ let !f = mkLit sym ty+ ss = indexSeqMap $ \i -> f (first + i)+ in case bound of+ Inf -> VStream ss+ Nat bound' -> VSeq (bound' - first) ss++{-# INLINE fromToByV #-}+-- @[ 0 .. 10 by 2 ]@+fromToByV :: Backend sym => sym -> Prim sym+fromToByV sym =+ PFinPoly \first ->+ PFinPoly \lst ->+ PFinPoly \stride ->+ PTyPoly \ty ->+ PVal+ let !f = mkLit sym ty+ ss = indexSeqMap $ \i -> f (first + i*stride)+ in VSeq (1 + ((lst - first) `div` stride)) ss++{-# INLINE fromToByLessThanV #-}+-- @[ 0 .. <10 by 2 ]@+fromToByLessThanV :: Backend sym => sym -> Prim sym+fromToByLessThanV sym =+ PFinPoly \first ->+ PNumPoly \bound ->+ PFinPoly \stride ->+ PTyPoly \ty ->+ PVal+ 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+++{-# INLINE fromToDownByV #-}+-- @[ 10 .. 0 down by 2 ]@+fromToDownByV :: Backend sym => sym -> Prim sym+fromToDownByV sym =+ PFinPoly \first ->+ PFinPoly \lst ->+ PFinPoly \stride ->+ PTyPoly \ty ->+ PVal+ let !f = mkLit sym ty+ ss = indexSeqMap $ \i -> f (first - i*stride)+ in VSeq (1 + ((first - lst) `div` stride)) ss++{-# INLINE fromToDownByGreaterThanV #-}+-- @[ 10 .. >0 down by 2 ]@+fromToDownByGreaterThanV :: Backend sym => sym -> Prim sym+fromToDownByGreaterThanV sym =+ PFinPoly \first ->+ PFinPoly \bound ->+ PFinPoly \stride ->+ PTyPoly \ty ->+ PVal+ let !f = mkLit sym ty+ ss = indexSeqMap $ \i -> f (first - i*stride)+ in VSeq ((first - bound + stride - 1) `div` stride) ss+ {-# INLINE infFromV #-} infFromV :: Backend sym => sym -> Prim sym infFromV sym =@@ -1621,7 +1551,7 @@ PFun \x -> PPrim do mx <- sDelay sym x- return $ VStream $ IndexSeqMap $ \i ->+ return $ VStream $ indexSeqMap $ \i -> do x' <- mx i' <- integerLit sym i addV sym ty x' =<< intV sym i' ty@@ -1638,37 +1568,14 @@ y <- next d <- subV sym ty y x pure (x,d))- return $ VStream $ IndexSeqMap $ \i -> do+ return $ VStream $ indexSeqMap $ \i -> do (x,d) <- mxd i' <- integerLit sym i addV sym ty x =<< mulV sym ty d =<< intV sym i' ty -- Shifting --------------------------------------------------- -barrelShifter :: Backend sym =>- sym ->- (SeqMap sym -> Integer -> SEval sym (SeqMap sym))- {- ^ concrete shifting operation -} ->- SeqMap sym {- ^ initial value -} ->- [SBit sym] {- ^ bits of shift amount, in big-endian order -} ->- SEval sym (SeqMap sym)-barrelShifter sym shift_op = go- where- go x [] = return x - go x (b:bs)- | Just True <- bitAsLit sym b- = do x_shft <- shift_op x (2 ^ length bs)- go x_shft bs-- | Just False <- bitAsLit sym b- = do go x bs-- | otherwise- = do x_shft <- shift_op x (2 ^ length bs)- x' <- memoMap sym (mergeSeqMap sym b x_shft x)- go x' bs- {-# INLINE shiftLeftReindex #-} shiftLeftReindex :: Nat' -> Integer -> Integer -> Maybe Integer shiftLeftReindex sz i shft =@@ -1695,30 +1602,8 @@ Inf -> evalPanic "cannot rotate infinite sequence" [] Nat n -> Just ((i+n-shft) `mod` n) --- | Compute the list of bits in an integer in big-endian order.--- Fails if neither the sequence length nor the type value--- provide an upper bound for the integer.-enumerateIntBits :: Backend sym =>- sym ->- Nat' ->- TValue ->- SInteger sym ->- SEval sym [SBit sym]-enumerateIntBits sym (Nat n) _ idx = enumerateIntBits' sym n idx-enumerateIntBits _sym Inf _ _ = liftIO (X.throw (UnsupportedSymbolicOp "unbounded integer shifting")) --- | Compute the list of bits in an integer in big-endian order.--- The integer argument is a concrete upper bound for--- the symbolic integer.-enumerateIntBits' :: Backend sym =>- sym ->- Integer ->- SInteger sym ->- SEval sym [SBit sym]-enumerateIntBits' sym n idx =- do w <- wordFromInt sym (widthInteger n) idx- unpackWord sym w-+{-# INLINE logicShift #-} -- | Generic implementation of shifting. -- Uses the provided word-level operation to perform the shift, when -- possible. Otherwise falls back on a barrel shifter that uses@@ -1749,16 +1634,19 @@ PFun \y -> PPrim do xs' <- xs- y' <- asIndex sym "shift" ix =<< y+ y' <- asIndex sym "shift" ix <$> y case y' of Left int_idx -> do pneg <- intLessThan sym int_idx =<< integerLit sym 0 iteValue sym pneg- (intShifter sym nm wopNeg reindexNeg m ix a xs' =<< shrinkRange sym m ix =<< intNegate sym int_idx)- (intShifter sym nm wopPos reindexPos m ix a xs' =<< shrinkRange sym m ix int_idx)+ (intShifter sym nm wopNeg reindexNeg m a xs' =<< shrinkRange sym m ix =<< intNegate sym int_idx)+ (intShifter sym nm wopPos reindexPos m a xs' =<< shrinkRange sym m ix int_idx) Right idx -> wordShifter sym nm wopPos reindexPos m a xs' idx +++{-# INLINE intShifter #-} intShifter :: Backend sym => sym -> String ->@@ -1766,36 +1654,18 @@ (Nat' -> Integer -> Integer -> Maybe Integer) -> Nat' -> TValue ->- TValue -> GenValue sym -> SInteger sym -> SEval sym (GenValue sym)-intShifter sym nm wop reindex m ix a xs idx =- do let shiftOp vs shft =- memoMap sym $ IndexSeqMap $ \i ->- case reindex m i shft of- Nothing -> zeroV sym a- Just i' -> lookupSeqMap vs i'- case xs of- VWord w x ->- return $ VWord w $ do- x >>= \case- WordVal x' -> WordVal <$> (wop x' =<< wordFromInt sym w idx)- LargeBitsVal n bs0 ->- do idx_bits <- enumerateIntBits sym m ix idx- LargeBitsVal n <$> barrelShifter sym shiftOp bs0 idx_bits-- VSeq w vs0 ->- do idx_bits <- enumerateIntBits sym m ix idx- VSeq w <$> barrelShifter sym shiftOp vs0 idx_bits-- VStream vs0 ->- do idx_bits <- enumerateIntBits sym m ix idx- VStream <$> barrelShifter sym shiftOp vs0 idx_bits-- _ -> evalPanic "expected sequence value in shift operation" [nm]+intShifter sym nm wop reindex m a xs idx =+ case xs of+ VWord w x -> VWord w <$> shiftWordByInteger sym wop (reindex m) x idx+ VSeq w vs -> VSeq w <$> shiftSeqByInteger sym (mergeValue sym) (reindex m) (zeroV sym a) m vs idx+ VStream vs -> VStream <$> shiftSeqByInteger sym (mergeValue sym) (reindex m) (zeroV sym a) m vs idx+ _ -> evalPanic "expected sequence value in shift operation" [nm] +{-# INLINE wordShifter #-} wordShifter :: Backend sym => sym -> String ->@@ -1807,31 +1677,15 @@ WordValue sym -> SEval sym (GenValue sym) wordShifter sym nm wop reindex m a xs idx =- let shiftOp vs shft =- memoMap sym $ IndexSeqMap $ \i ->- case reindex m i shft of- Nothing -> zeroV sym a- Just i' -> lookupSeqMap vs i'- in case xs of- VWord w x ->- return $ VWord w $ do- x >>= \case- WordVal x' -> WordVal <$> (wop x' =<< asWordVal sym idx)- LargeBitsVal n bs0 ->- do idx_bits <- enumerateWordValue sym idx- LargeBitsVal n <$> barrelShifter sym shiftOp bs0 idx_bits+ case xs of+ VWord w x -> VWord w <$> shiftWordByWord sym wop (reindex m) x idx+ VSeq w vs -> VSeq w <$> shiftSeqByWord sym (mergeValue sym) (reindex m) (zeroV sym a) (Nat w) vs idx+ VStream vs -> VStream <$> shiftSeqByWord sym (mergeValue sym) (reindex m) (zeroV sym a) Inf vs idx+ _ -> evalPanic "expected sequence value in shift operation" [nm] - VSeq w vs0 ->- do idx_bits <- enumerateWordValue sym idx- VSeq w <$> barrelShifter sym shiftOp vs0 idx_bits - VStream vs0 ->- do idx_bits <- enumerateWordValue sym idx- VStream <$> barrelShifter sym shiftOp vs0 idx_bits - _ -> evalPanic "expected sequence value in shift operation" [nm]--+{-# INLINE shiftShrink #-} shiftShrink :: Backend sym => sym -> Nat' -> TValue -> SInteger sym -> SEval sym (SInteger sym) shiftShrink _sym Inf _ x = return x shiftShrink sym (Nat w) _ x =@@ -1839,6 +1693,7 @@ p <- intLessThan sym w' x iteInteger sym p w' x +{-# INLINE rotateShrink #-} rotateShrink :: Backend sym => sym -> Nat' -> TValue -> SInteger sym -> SEval sym (SInteger sym) rotateShrink _sym Inf _ _ = panic "rotateShrink" ["expected finite sequence in rotate"] rotateShrink sym (Nat 0) _ _ = integerLit sym 0@@ -1846,6 +1701,30 @@ do w' <- integerLit sym w intMod sym x w' +{-# INLINE sshrV #-}+sshrV :: Backend sym => sym -> Prim sym+sshrV sym =+ PFinPoly \n ->+ PTyPoly \ix ->+ PWordFun \x ->+ PStrict \y ->+ PPrim $+ case asIndex sym ">>$" ix y of+ Left i ->+ do pneg <- intLessThan sym i =<< integerLit sym 0+ VWord n <$> mergeWord' sym+ pneg+ (do i' <- shiftShrink sym (Nat n) ix =<< intNegate sym i+ amt <- wordFromInt sym n i'+ wordVal <$> wordShiftLeft sym x amt)+ (do i' <- shiftShrink sym (Nat n) ix i+ amt <- wordFromInt sym n i'+ wordVal <$> wordSignedShiftRight sym x amt)++ Right wv ->+ do amt <- asWordVal sym wv+ VWord n . wordVal <$> wordSignedShiftRight sym x amt+ -- Miscellaneous --------------------------------------------------------------- {-# SPECIALIZE errorV ::@@ -1860,38 +1739,9 @@ TValue -> String -> SEval sym (GenValue sym)-errorV sym ty0 msg =- do stk <- sGetCallStack sym- loop stk ty0- where- err stk = sWithCallStack sym stk (cryUserError sym msg)-- loop stk = \case- TVBit -> err stk- TVInteger -> err stk- TVIntMod _ -> err stk- TVRational -> err stk- TVArray{} -> err stk- TVFloat {} -> err stk-- -- sequences- TVSeq w ety- | isTBit ety -> return $ VWord w $ return $ LargeBitsVal w $ IndexSeqMap $ \_ -> err stk- | otherwise -> return $ VSeq w $ IndexSeqMap $ \_ -> loop stk ety-- TVStream ety -> return $ VStream $ IndexSeqMap $ \_ -> loop stk ety-- -- functions- TVFun _ bty -> lam sym (\ _ -> loop stk bty)-- -- tuples- TVTuple tys -> return $ VTuple (map (\t -> loop stk t) tys)-- -- records- TVRec fields -> return $ VRecord $ fmap (\t -> loop stk t) $ fields-- TVAbstract {} -> err stk- TVNewtype {} -> err stk+errorV sym _ty msg =+ do stk <- sGetCallStack sym+ sWithCallStack sym stk (cryUserError sym msg) {-# INLINE valueToChar #-} @@ -1900,7 +1750,7 @@ -- Otherwise, return a '?' character valueToChar :: Backend sym => sym -> GenValue sym -> SEval sym Char valueToChar sym (VWord 8 wval) =- do w <- asWordVal sym =<< wval+ do w <- asWordVal sym wval pure $! fromMaybe '?' (wordAsChar sym w) valueToChar _ _ = evalPanic "valueToChar" ["Not an 8-bit bitvector"] @@ -1910,90 +1760,7 @@ valueToString sym (VSeq n vals) = traverse (valueToChar sym =<<) (enumerateSeqMap n vals) valueToString _ _ = evalPanic "valueToString" ["Not a finite sequence"] --- Merge and if/then/else -{-# INLINE iteValue #-}-iteValue :: Backend sym =>- sym ->- SBit sym ->- SEval sym (GenValue sym) ->- SEval sym (GenValue sym) ->- SEval sym (GenValue sym)-iteValue sym b x y- | Just True <- bitAsLit sym b = x- | Just False <- bitAsLit sym b = y- | otherwise = mergeValue' sym b x y--{-# INLINE mergeWord #-}-mergeWord :: Backend sym =>- sym ->- SBit sym ->- WordValue sym ->- WordValue sym ->- SEval sym (WordValue sym)-mergeWord sym c (WordVal w1) (WordVal w2) =- WordVal <$> iteWord sym c w1 w2-mergeWord sym c w1 w2 =- LargeBitsVal (wordValueSize sym w1) <$> memoMap sym (mergeSeqMap sym c (asBitsMap sym w1) (asBitsMap sym w2))--{-# INLINE mergeWord' #-}-mergeWord' :: Backend sym =>- sym ->- SBit sym ->- SEval sym (WordValue sym) ->- SEval sym (WordValue sym) ->- SEval sym (WordValue sym)-mergeWord' sym = mergeEval sym (mergeWord sym)--{-# INLINE mergeValue' #-}-mergeValue' :: Backend sym =>- sym ->- SBit sym ->- SEval sym (GenValue sym) ->- SEval sym (GenValue sym) ->- SEval sym (GenValue sym)-mergeValue' sym = mergeEval sym (mergeValue sym)--mergeValue :: Backend sym =>- sym ->- SBit sym ->- GenValue sym ->- GenValue sym ->- SEval sym (GenValue sym)-mergeValue sym c v1 v2 =- case (v1, v2) of- (VRecord fs1 , VRecord fs2 ) ->- do let res = zipRecords (\_lbl -> mergeValue' sym c) fs1 fs2- case res of- Left f -> panic "Cryptol.Eval.Generic" [ "mergeValue: incompatible record values", show f ]- Right r -> pure (VRecord r)- (VTuple vs1 , VTuple vs2 ) | length vs1 == length vs2 ->- pure $ VTuple $ zipWith (mergeValue' sym c) vs1 vs2- (VBit b1 , VBit b2 ) -> VBit <$> iteBit sym c b1 b2- (VInteger i1 , VInteger i2 ) -> VInteger <$> iteInteger sym c i1 i2- (VRational q1, VRational q2) -> VRational <$> iteRational sym c q1 q2- (VFloat f1 , VFloat f2) -> VFloat <$> iteFloat sym c f1 f2- (VWord n1 w1 , VWord n2 w2 ) | n1 == n2 -> pure $ VWord n1 $ mergeWord' sym c w1 w2- (VSeq n1 vs1 , VSeq n2 vs2 ) | n1 == n2 -> VSeq n1 <$> memoMap sym (mergeSeqMap sym c vs1 vs2)- (VStream vs1 , VStream vs2 ) -> VStream <$> memoMap sym (mergeSeqMap sym c vs1 vs2)- (f1@VFun{} , f2@VFun{} ) -> lam sym $ \x -> mergeValue' sym c (fromVFun sym f1 x) (fromVFun sym f2 x)- (f1@VPoly{} , f2@VPoly{} ) -> tlam sym $ \x -> mergeValue' sym c (fromVPoly sym f1 x) (fromVPoly sym f2 x)- (_ , _ ) -> panic "Cryptol.Eval.Generic"- [ "mergeValue: incompatible values" ]--{-# INLINE mergeSeqMap #-}-mergeSeqMap :: Backend sym =>- sym ->- SBit sym ->- SeqMap sym ->- SeqMap sym ->- SeqMap sym-mergeSeqMap sym c x y =- IndexSeqMap $ \i ->- iteValue sym c (lookupSeqMap x i) (lookupSeqMap y i)--- foldlV :: Backend sym => sym -> Prim sym foldlV sym = PNumPoly \_n ->@@ -2005,7 +1772,7 @@ PPrim case v of VSeq n m -> go0 f z (enumerateSeqMap n m)- VWord _n wv -> go0 f z . map (pure . VBit) =<< (enumerateWordValue sym =<< wv)+ VWord _n wv -> go0 f z . map (pure . VBit) =<< (enumerateWordValue sym wv) _ -> panic "Cryptol.Eval.Generic.foldlV" ["Expected finite sequence"] where go0 _f a [] = a@@ -2029,7 +1796,7 @@ PPrim case v of VSeq n m -> go0 f z (enumerateSeqMap n m)- VWord _n wv -> go0 f z . map (pure . VBit) =<< (enumerateWordValue sym =<< wv)+ VWord _n wv -> go0 f z . map (pure . VBit) =<< (enumerateWordValue sym wv) _ -> panic "Cryptol.Eval.Generic.foldlV" ["Expected finite sequence"] where go0 _f a [] = a@@ -2081,9 +1848,9 @@ xs' <- xs case xs' of VWord n w ->- do m <- asBitsMap sym <$> w- m' <- sparkParMap sym f' n m- pure (VWord n (pure (LargeBitsVal n m')))+ do let m = asBitsMap sym w+ m' <- sparkParMap sym (\x -> f' (VBit <$> x)) n m+ VWord n <$> (bitmapWordVal sym n (fromVBit <$> m')) VSeq n m -> VSeq n <$> sparkParMap sym f' n m @@ -2093,12 +1860,12 @@ sparkParMap :: Backend sym => sym ->- (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) ->+ (SEval sym a -> SEval sym (GenValue sym)) -> Integer ->- SeqMap sym ->- SEval sym (SeqMap sym)+ SeqMap sym a ->+ SEval sym (SeqMap sym (GenValue sym)) sparkParMap sym f n m =- finiteSeqMap <$> mapM (sSpark sym . g) (enumerateSeqMap n m)+ finiteSeqMap sym <$> mapM (sSpark sym . g) (enumerateSeqMap n m) where g x = do z <- sDelay sym (f x)@@ -2149,9 +1916,8 @@ , "fpPosInf" ~> fpConst (fpPosInf sym) , "fpFromBits" ~> PFinPoly \e -> PFinPoly \p -> PWordFun \w -> PPrim (VFloat <$> fpFromBits sym e p w)- , "fpToBits" ~> PFinPoly \e -> PFinPoly \p -> PFloatFun \x -> PVal- $ VWord (e+p)- $ WordVal <$> fpToBits sym x+ , "fpToBits" ~> PFinPoly \e -> PFinPoly \p -> PFloatFun \x -> PPrim+ (VWord (e+p) . wordVal <$> fpToBits sym x) , "=.=" ~> PFinPoly \_ -> PFinPoly \_ -> PFloatFun \x -> PFloatFun \y -> PPrim (VBit <$> fpLogicalEq sym x y) @@ -2272,6 +2038,9 @@ unary (roundToEvenV sym)) -- Bitvector specific operations+ , ("toSignedInteger"+ , {-# SCC "Prelude::toSignedInteger" #-}+ toSignedIntegerV sym) , ("/$" , {-# SCC "Prelude::(/$)" #-} sdivV sym) , ("%$" , {-# SCC "Prelude::(%$)" #-}@@ -2308,6 +2077,20 @@ , {-# SCC "Prelude::fromToLessThan" #-} fromToLessThanV sym) + , ("fromToBy" , {-# SCC "Prelude::fromToBy" #-}+ fromToByV sym)++ , ("fromToByLessThan",+ {-# SCC "Prelude::fromToByLessThan" #-}+ fromToByLessThanV sym)++ , ("fromToDownBy", {-# SCC "Prelude::fromToDownBy" #-}+ fromToDownByV sym)++ , ("fromToDownByGreaterThan"+ , {-# SCC "Prelude::fromToDownByGreaterThan" #-}+ fromToDownByGreaterThanV sym)+ -- Sequence manipulations , ("#" , {-# SCC "Prelude::(#)" #-} PFinPoly \front ->@@ -2315,37 +2098,69 @@ PTyPoly \elty -> PFun \l -> PFun \r ->- PPrim (join (ccatV sym (Nat front) back elty <$> l <*> r)))+ PPrim $ ccatV sym front back elty l r) , ("join" , {-# SCC "Prelude::join" #-} PNumPoly \parts -> PFinPoly \each -> PTyPoly \a ->- PStrict \x ->+ PFun \x -> PPrim $ joinV sym parts each a x) , ("split" , {-# SCC "Prelude::split" #-}- ecSplitV sym)+ PNumPoly \parts ->+ PFinPoly \each ->+ PTyPoly \a ->+ PFun \val ->+ PPrim $ splitV sym parts each a val) - , ("splitAt" , {-# SCC "Prelude::splitAt" #-}+ , ("take" , {-# SCC "Preldue::take" #-} PNumPoly \front ->- PNumPoly \back ->- PTyPoly \a ->- PStrict \x ->- PPrim $ splitAtV sym front back a x)+ PNumPoly \back ->+ PTyPoly \a ->+ PFun \xs ->+ PPrim $ takeV sym front back a xs) + , ("drop" , {-# SCC "Preldue::drop" #-}+ PFinPoly \front ->+ PNumPoly \back ->+ PTyPoly \a ->+ PFun \xs ->+ PPrim $ dropV sym front back a xs)+ , ("reverse" , {-# SCC "Prelude::reverse" #-}- PFinPoly \_a ->- PTyPoly \_b ->- PStrict \xs ->- PPrim $ reverseV sym xs)+ PFinPoly \a ->+ PTyPoly \b ->+ PFun \xs ->+ PPrim $ reverseV sym a b xs) , ("transpose" , {-# SCC "Prelude::transpose" #-} PNumPoly \a -> PNumPoly \b -> PTyPoly \c ->- PStrict \xs ->- PPrim $ transposeV sym a b c xs)+ PFun \xs ->+ PPrim $ transposeV sym a b c =<< xs)++ -- Shifts and rotates+ , ("<<" , {-# SCC "Prelude::(<<)" #-}+ logicShift sym "<<" shiftShrink+ (wordShiftLeft sym) (wordShiftRight sym)+ shiftLeftReindex shiftRightReindex)+ , (">>" , {-# SCC "Prelude::(>>)" #-}+ logicShift sym ">>" shiftShrink+ (wordShiftRight sym) (wordShiftLeft sym)+ shiftRightReindex shiftLeftReindex)+ , ("<<<" , {-# SCC "Prelude::(<<<)" #-}+ logicShift sym "<<<" rotateShrink+ (wordRotateLeft sym) (wordRotateRight sym)+ rotateLeftReindex rotateRightReindex)+ , (">>>" , {-# SCC "Prelude::(>>>)" #-}+ logicShift sym ">>>" rotateShrink+ (wordRotateRight sym) (wordRotateLeft sym)+ rotateRightReindex rotateLeftReindex)++ , (">>$" , {-# SCC "Prelude::(>>$)" #-}+ sshrV sym) -- Misc
src/Cryptol/Eval/Reference.lhs view
@@ -251,7 +251,7 @@ > instance Semigroup Env where > l <> r = Env > { envVars = envVars l <> envVars r-> , envTypes = envTypes l <> envTypes r +> , envTypes = envTypes l <> envTypes r > } > > instance Monoid Env where@@ -523,7 +523,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 (ntName nt, pure val) env > where > val = foldr tabs con (ntParams nt) > con = VFun (\x -> x)@@ -541,7 +541,7 @@ > evalPrim :: Name -> Value > evalPrim n > | Just i <- asPrim n, Just v <- Map.lookup i primTable = v-> | otherwise = evalPanic "evalPrim" ["Unimplemented primitive", show n]+> | otherwise = evalPanic "evalPrim" ["Unimplemented primitive", show (pp n)] Cryptol primitives fall into several groups, mostly delineated by corresponding type classes:@@ -560,13 +560,15 @@ * Comparison: `<`, `>`, `<=`, `>=`, `==`, `!=` -* Sequences: `#`, `join`, `split`, `splitAt`, `reverse`, `transpose`+* Sequences: `#`, `join`, `split`, `take`, `drop`, `reverse`, `transpose` * Shifting: `<<`, `>>`, `<<<`, `>>>` * Indexing: `@`, `@@`, `!`, `!!`, `update`, `updateEnd` -* Enumerations: `fromTo`, `fromThenTo`, `infFrom`, `infFromThen`+* Enumerations: `fromTo`, `fromThenTo`, `fromToLessThan`, `fromToBy`,+ `fromToByLessThan`, `fromToDownBy`, `fromToDownByGreaterThan`,+ `infFrom`, `infFromThen` * Polynomials: `pmult`, `pdiv`, `pmod` @@ -734,17 +736,21 @@ > do vs <- fromVList <$> val > indexFront (nMul parts (Nat each)) vs (i * each + j) >-> , "splitAt" ~> vFinPoly $ \front -> pure $+> , "take" ~> VNumPoly $ \front -> pure $+> VNumPoly $ \back -> pure $+> VPoly $ \_a -> pure $+> VFun $ \v ->+> pure $ generateV front $ \i ->+> do vs <- fromVList <$> v+> indexFront (nAdd front back) vs i+>+> , "drop" ~> vFinPoly $ \front -> pure $ > VNumPoly $ \back -> pure $ > VPoly $ \_a -> pure $ > VFun $ \v ->-> let xs = pure $ generateV (Nat front) $ \i ->-> do vs <- fromVList <$> v-> indexFront (nAdd (Nat front) back) vs i-> ys = pure $ generateV back $ \i ->-> do vs <- fromVList <$> v-> indexFront (nAdd (Nat front) back) vs (front+i)-> in pure (VTuple [ xs, ys ])+> pure $ generateV back $ \i ->+> do vs <- fromVList <$> v+> indexFront (nAdd (Nat front) back) vs (front+i) > > , "reverse" ~> vFinPoly $ \n -> pure $ > VPoly $ \_a -> pure $@@ -778,18 +784,71 @@ > -- Enumerations > , "fromTo" ~> vFinPoly $ \first -> pure $ > vFinPoly $ \lst -> pure $-> VPoly $ \ty ->-> let f i = literal i ty-> in pure (VList (Nat (1 + lst - first)) (map f [first .. lst]))+> VPoly $ \ty -> pure $+> let f i = literal i ty in+> VList (Nat (1 + lst - first)) (map f [first .. lst]) >+> , "fromToLessThan" ~>+> vFinPoly $ \first -> pure $+> VNumPoly $ \bound -> pure $+> VPoly $ \ty -> pure $+> let f i = literal i ty in+> case bound of+> Inf -> VList Inf (map f [first ..])+> Nat bound' ->+> let len = bound' - first in+> VList (Nat len) (map f (genericTake len [first ..]))+>+> , "fromToBy" ~> vFinPoly $ \first -> pure $+> vFinPoly $ \lst -> pure $+> vFinPoly $ \stride -> pure $+> VPoly $ \ty -> pure $+> let f i = literal i ty in+> let vs = [ f (first + i*stride) | i <- [0..] ] in+> let len = 1 + ((lst-first) `div` stride) in+> VList (Nat len) (genericTake len vs)+>+> , "fromToByLessThan" ~>+> vFinPoly $ \first -> pure $+> VNumPoly $ \bound -> pure $+> vFinPoly $ \stride -> pure $+> VPoly $ \ty -> pure $+> let f i = literal i ty in+> let vs = [ f (first + i*stride) | i <- [0..] ] in+> case bound of+> Inf -> VList Inf vs+> Nat bound' ->+> let len = (bound'-first+stride-1) `div` stride in+> VList (Nat len) (genericTake len vs)+>+> , "fromToDownBy" ~>+> vFinPoly $ \first -> pure $+> vFinPoly $ \lst -> pure $+> vFinPoly $ \stride -> pure $+> VPoly $ \ty -> pure $+> let f i = literal i ty in+> let vs = [ f (first - i*stride) | i <- [0..] ] in+> let len = 1 + ((first-lst) `div` stride) in+> VList (Nat len) (genericTake len vs)+>+> , "fromToDownByGreaterThan" ~>+> vFinPoly $ \first -> pure $+> vFinPoly $ \lst -> pure $+> vFinPoly $ \stride -> pure $+> VPoly $ \ty -> pure $+> let f i = literal i ty in+> let vs = [ f (first - i*stride) | i <- [0..] ] in+> let len = (first-lst+stride-1) `div` stride in+> VList (Nat len) (genericTake len vs)+> > , "fromThenTo" ~> vFinPoly $ \first -> pure $ > vFinPoly $ \next -> pure $ > vFinPoly $ \_lst -> pure $ > VPoly $ \ty -> pure $-> vFinPoly $ \len ->-> let f i = literal i ty-> in pure (VList (Nat len)-> (map f (genericTake len [first, next ..])))+> vFinPoly $ \len -> pure $+> let f i = literal i ty in+> VList (Nat len)+> (map f (genericTake len [first, next ..])) > > , "infFrom" ~> VPoly $ \ty -> pure $ > VFun $ \first ->@@ -1711,11 +1770,10 @@ > case traverse isBit vs of > Just bs -> ppBV opts (mkBv n (bitsToInteger bs)) > Nothing -> ppList (map (ppEValue opts) vs)-> where ppList docs = brackets (fsep (punctuate comma docs))-> isBit v = case v of Value (VBit b) -> Just b+> where isBit v = case v of Value (VBit b) -> Just b > _ -> Nothing-> VTuple vs -> parens (sep (punctuate comma (map (ppEValue opts) vs)))-> VRecord fs -> braces (sep (punctuate comma (map ppField fs)))+> VTuple vs -> ppTuple (map (ppEValue opts) vs)+> VRecord fs -> ppRecord (map ppField fs) > where ppField (f,r) = pp f <+> char '=' <+> ppEValue opts r > VFun _ -> text "<function>" > VPoly _ -> text "<polymorphic value>"@@ -1732,7 +1790,7 @@ > evaluate expr minp = return (Right (val, modEnv), []) > where > modEnv = M.minpModuleEnv minp-> extDgs = concatMap mDecls (M.loadedModules modEnv)+> extDgs = concatMap mDecls (M.loadedModules modEnv) ++ M.deDecls (M.meDynEnv modEnv) > nts = Map.elems (M.loadedNewtypes modEnv) > env = foldl evalDeclGroup (foldl evalNewtypeDecl mempty nts) extDgs > val = evalExpr env expr
src/Cryptol/Eval/SBV.hs view
@@ -23,21 +23,22 @@ import qualified Control.Exception as X import Control.Monad.IO.Class (MonadIO(..))-import Data.Bits (bit, shiftL) import qualified Data.Map as Map import qualified Data.Text as T import Data.SBV.Dynamic as SBV import Cryptol.Backend-import Cryptol.Backend.Monad ( EvalError(..), Unsupported(..) )+import Cryptol.Backend.Monad (Unsupported(..), EvalError(..) ) import Cryptol.Backend.SBV+import Cryptol.Backend.SeqMap+import Cryptol.Backend.WordValue import Cryptol.Eval.Type (TValue(..)) import Cryptol.Eval.Generic import Cryptol.Eval.Prims import Cryptol.Eval.Value-import Cryptol.TypeCheck.Solver.InfNat (Nat'(..), widthInteger)+import Cryptol.TypeCheck.Solver.InfNat (Nat'(..)) import Cryptol.Utils.Ident -- Values ----------------------------------------------------------------------@@ -52,36 +53,9 @@ Map.union (genericPrimTable sym getEOpts) $ Map.fromList $ map (\(n, v) -> (prelPrim (T.pack n), v)) - [ (">>$" , sshrV sym)-- -- Shifts and rotates- , ("<<" , logicShift sym "<<"- shiftShrink- (\x y -> pure (shl x y))- (\x y -> pure (lshr x y))- shiftLeftReindex shiftRightReindex)-- , (">>" , logicShift sym ">>"- shiftShrink- (\x y -> pure (lshr x y))- (\x y -> pure (shl x y))- shiftRightReindex shiftLeftReindex)-- , ("<<<" , logicShift sym "<<<"- rotateShrink- (\x y -> pure (SBV.svRotateLeft x y))- (\x y -> pure (SBV.svRotateRight x y))- rotateLeftReindex rotateRightReindex)-- , (">>>" , logicShift sym ">>>"- rotateShrink- (\x y -> pure (SBV.svRotateRight x y))- (\x y -> pure (SBV.svRotateLeft x y))- rotateRightReindex rotateLeftReindex)-- -- Indexing and updates- , ("@" , indexPrim sym (indexFront sym) (indexFront_bits sym) (indexFront sym))- , ("!" , indexPrim sym (indexBack sym) (indexBack_bits sym) (indexBack sym))+ [ -- Indexing and updates+ ("@" , indexPrim sym IndexForward (indexFront sym) (indexFront_segs sym))+ , ("!" , indexPrim sym IndexBackward (indexFront sym) (indexFront_segs sym)) , ("update" , updatePrim sym (updateFrontSym_word sym) (updateFrontSym sym)) , ("updateEnd" , updatePrim sym (updateBackSym_word sym) (updateBackSym sym))@@ -92,7 +66,7 @@ SBV -> Nat' -> TValue ->- SeqMap SBV ->+ SeqMap SBV (GenValue SBV) -> TValue -> SVal -> SEval SBV Value@@ -102,125 +76,77 @@ | Nat n <- mblen , TVSeq wlen TVBit <- a- = do wvs <- traverse (fromWordVal "indexFront" =<<) (enumerateSeqMap n xs)- case asWordList wvs of+ = do wvs <- traverse (fromWordVal "indexFront" <$>) (enumerateSeqMap n xs)+ asWordList sym wvs >>= \case Just ws -> do z <- wordLit sym wlen 0- return $ VWord wlen $ pure $ WordVal $ SBV.svSelect ws z idx- Nothing -> folded+ return $ VWord wlen $ wordVal $ SBV.svSelect ws z idx+ Nothing -> folded' - | otherwise- = folded+ | otherwise = folded' + where k = SBV.kindOf idx- def = zeroV sym a- f n y = iteValue sym (SBV.svEqual idx (SBV.svInteger k n)) (lookupSeqMap xs n) y++ f n (Just y) = Just $ iteValue sym (SBV.svEqual idx (SBV.svInteger k n)) (lookupSeqMap xs n) y+ f n Nothing = Just $ lookupSeqMap xs n++ folded' =+ case folded of+ Nothing -> raiseError sym (InvalidIndex Nothing)+ Just m -> m+ folded = case k of KBounded _ w -> case mblen of- Nat n | n < 2^w -> foldr f def [0 .. n-1]- _ -> foldr f def [0 .. 2^w - 1]+ Nat n | n < 2^w -> foldr f Nothing [0 .. n-1]+ _ -> foldr f Nothing [0 .. 2^w - 1] _ -> case mblen of- Nat n -> foldr f def [0 .. n-1]- Inf -> liftIO (X.throw (UnsupportedSymbolicOp "unbounded integer indexing"))--indexBack ::- SBV ->- Nat' ->- TValue ->- SeqMap SBV ->- TValue ->- SWord SBV ->- SEval SBV Value-indexBack sym (Nat n) a xs ix idx = indexFront sym (Nat n) a (reverseSeqMap n xs) ix idx-indexBack _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["indexBack"]--indexFront_bits ::- SBV ->- Nat' ->- TValue ->- SeqMap SBV ->- TValue ->- [SBit SBV] ->- SEval SBV Value-indexFront_bits sym mblen _a xs _ix bits0 = go 0 (length bits0) bits0- where- go :: Integer -> Int -> [SBit SBV] -> SEval SBV Value- go i _k []- -- For indices out of range, fail- | Nat n <- mblen- , i >= n- = raiseError sym (InvalidIndex (Just i))-- | otherwise- = lookupSeqMap xs i-- go i k (b:bs)- -- Fail early when all possible indices we could compute from here- -- are out of bounds- | Nat n <- mblen- , (i `shiftL` k) >= n- = raiseError sym (InvalidIndex Nothing)-- | otherwise- = iteValue sym b- (go ((i `shiftL` 1) + 1) (k-1) bs)- (go (i `shiftL` 1) (k-1) bs)-+ Nat n -> foldr f Nothing [0 .. n-1]+ Inf -> Just (liftIO (X.throw (UnsupportedSymbolicOp "unbounded integer indexing"))) -indexBack_bits ::+indexFront_segs :: SBV -> Nat' -> TValue ->- SeqMap SBV ->+ SeqMap SBV (GenValue SBV) -> TValue ->- [SBit SBV] ->+ Integer ->+ [IndexSegment SBV] -> SEval SBV Value-indexBack_bits sym (Nat n) a xs ix idx = indexFront_bits sym (Nat n) a (reverseSeqMap n xs) ix idx-indexBack_bits _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["indexBack_bits"]-+indexFront_segs sym mblen a xs ix _idx_bits [WordIndexSegment w] =+ indexFront sym mblen a xs ix w --- | Compare a symbolic word value with a concrete integer.-wordValueEqualsInteger :: SBV -> WordValue SBV -> Integer -> SEval SBV (SBit SBV)-wordValueEqualsInteger sym wv i- | wordValueSize sym wv < widthInteger i = return SBV.svFalse- | otherwise =- case wv of- WordVal w -> return $ SBV.svEqual w (literalSWord (SBV.intSizeOf w) i)- _ -> bitsAre i <$> enumerateWordValueRev sym wv -- little-endian+indexFront_segs sym mblen _a xs _ix idx_bits segs =+ do xs' <- barrelShifter sym (mergeValue sym) shiftOp mblen xs idx_bits segs+ lookupSeqMap xs' 0 where- bitsAre :: Integer -> [SBit SBV] -> SBit SBV- bitsAre n [] = SBV.svBool (n == 0)- bitsAre n (b : bs) = SBV.svAnd (bitIs (odd n) b) (bitsAre (n `div` 2) bs)-- bitIs :: Bool -> SBit SBV -> SBit SBV- bitIs b x = if b then x else SBV.svNot x+ shiftOp vs amt = pure (indexSeqMap (\i -> lookupSeqMap vs $! amt+i)) updateFrontSym :: SBV -> Nat' -> TValue ->- SeqMap SBV ->+ SeqMap SBV (GenValue SBV) -> Either (SInteger SBV) (WordValue SBV) -> SEval SBV (GenValue SBV) ->- SEval SBV (SeqMap SBV)+ SEval SBV (SeqMap SBV (GenValue SBV)) updateFrontSym sym _len _eltTy vs (Left idx) val = case SBV.svAsInteger idx of Just i -> return $ updateSeqMap vs i val- Nothing -> return $ IndexSeqMap $ \i ->+ Nothing -> return $ indexSeqMap $ \i -> do b <- intEq sym idx =<< integerLit sym i iteValue sym b val (lookupSeqMap vs i) updateFrontSym sym _len _eltTy vs (Right wv) val =- case wv of- WordVal w | Just j <- SBV.svAsInteger w ->- return $ updateSeqMap vs j val- _ ->- return $ IndexSeqMap $ \i ->+ wordValAsLit sym wv >>= \case+ Just j -> return $ updateSeqMap vs j val+ Nothing ->+ return $ indexSeqMap $ \i -> do b <- wordValueEqualsInteger sym wv i iteValue sym b val (lookupSeqMap vs i) @@ -234,56 +160,35 @@ SEval SBV (WordValue SBV) updateFrontSym_word _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["updateFrontSym_bits"] -updateFrontSym_word sym (Nat _) eltTy (LargeBitsVal n bv) idx val =- LargeBitsVal n <$> updateFrontSym sym (Nat n) eltTy bv idx val--updateFrontSym_word sym (Nat n) eltTy (WordVal bv) (Left idx) val =+updateFrontSym_word sym (Nat n) _eltTy w (Left idx) val = do idx' <- wordFromInt sym n idx- updateFrontSym_word sym (Nat n) eltTy (WordVal bv) (Right (WordVal idx')) val--updateFrontSym_word sym (Nat n) eltTy bv (Right wv) val =- case wv of- WordVal idx- | Just j <- SBV.svAsInteger idx ->- updateWordValue sym bv j (fromVBit <$> val)-- | WordVal bw <- bv ->- WordVal <$>- do b <- fromVBit <$> val- let sz = SBV.intSizeOf bw- let z = literalSWord sz 0- let znot = SBV.svNot z- let q = SBV.svSymbolicMerge (SBV.kindOf bw) True b znot z- let msk = SBV.svShiftRight (literalSWord sz (bit (sz-1))) idx- let bw' = SBV.svAnd bw (SBV.svNot msk)- return $! SBV.svXOr bw' (SBV.svAnd q msk)-- _ -> LargeBitsVal n <$> updateFrontSym sym (Nat n) eltTy (asBitsMap sym bv) (Right wv) val+ updateWordByWord sym IndexForward w (wordVal idx') (fromVBit <$> val)+updateFrontSym_word sym (Nat _n) _eltTy w (Right idx) val =+ updateWordByWord sym IndexForward w idx (fromVBit <$> val) updateBackSym :: SBV -> Nat' -> TValue ->- SeqMap SBV ->+ SeqMap SBV (GenValue SBV) -> Either (SInteger SBV) (WordValue SBV) -> SEval SBV (GenValue SBV) ->- SEval SBV (SeqMap SBV)+ SEval SBV (SeqMap SBV (GenValue SBV)) updateBackSym _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["updateBackSym"] updateBackSym sym (Nat n) _eltTy vs (Left idx) val = case SBV.svAsInteger idx of Just i -> return $ updateSeqMap vs (n - 1 - i) val- Nothing -> return $ IndexSeqMap $ \i ->+ Nothing -> return $ indexSeqMap $ \i -> do b <- intEq sym idx =<< integerLit sym (n - 1 - i) iteValue sym b val (lookupSeqMap vs i) updateBackSym sym (Nat n) _eltTy vs (Right wv) val =- case wv of- WordVal w | Just j <- SBV.svAsInteger w ->- return $ updateSeqMap vs (n - 1 - j) val- _ ->- return $ IndexSeqMap $ \i ->+ wordValAsLit sym wv >>= \case+ Just j -> return $ updateSeqMap vs (n - 1 - j) val+ Nothing ->+ return $ indexSeqMap $ \i -> do b <- wordValueEqualsInteger sym wv (n - 1 - i) iteValue sym b val (lookupSeqMap vs i) @@ -297,56 +202,9 @@ SEval SBV (WordValue SBV) updateBackSym_word _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["updateBackSym_bits"] -updateBackSym_word sym (Nat _) eltTy (LargeBitsVal n bv) idx val =- LargeBitsVal n <$> updateBackSym sym (Nat n) eltTy bv idx val--updateBackSym_word sym (Nat n) eltTy (WordVal bv) (Left idx) val =+updateBackSym_word sym (Nat n) _eltTy w (Left idx) val = do idx' <- wordFromInt sym n idx- updateBackSym_word sym (Nat n) eltTy (WordVal bv) (Right (WordVal idx')) val--updateBackSym_word sym (Nat n) eltTy bv (Right wv) val = do- case wv of- WordVal idx- | Just j <- SBV.svAsInteger idx ->- updateWordValue sym bv (n - 1 - j) (fromVBit <$> val)-- | WordVal bw <- bv ->- WordVal <$>- do b <- fromVBit <$> val- let sz = SBV.intSizeOf bw- let z = literalSWord sz 0- let znot = SBV.svNot z- let q = SBV.svSymbolicMerge (SBV.kindOf bw) True b znot z- let msk = SBV.svShiftLeft (literalSWord sz 1) idx- let bw' = SBV.svAnd bw (SBV.svNot msk)- return $! SBV.svXOr bw' (SBV.svAnd q msk)-- _ -> LargeBitsVal n <$> updateBackSym sym (Nat n) eltTy (asBitsMap sym bv) (Right wv) val---asWordList :: [WordValue SBV] -> Maybe [SWord SBV]-asWordList = go id- where go :: ([SWord SBV] -> [SWord SBV]) -> [WordValue SBV] -> Maybe [SWord SBV]- go f [] = Just (f [])- go f (WordVal x :vs) = go (f . (x:)) vs- go _f (LargeBitsVal _ _ : _) = Nothing--sshrV :: SBV -> Prim SBV-sshrV sym =- PNumPoly \n ->- PTyPoly \ix ->- PWordFun \x ->- PStrict \y ->- PPrim $- asIndex sym ">>$" ix y >>= \case- Left idx ->- do let w = toInteger (SBV.intSizeOf x)- let pneg = svLessThan idx (svInteger KUnbounded 0)- zneg <- shl x . svFromInteger w <$> shiftShrink sym n ix (SBV.svUNeg idx)- zpos <- ashr x . svFromInteger w <$> shiftShrink sym n ix idx- let z = svSymbolicMerge (kindOf x) True pneg zneg zpos- return . VWord w . pure . WordVal $ z+ updateWordByWord sym IndexBackward w (wordVal idx') (fromVBit <$> val)+updateBackSym_word sym (Nat _n) _eltTy w (Right idx) val =+ updateWordByWord sym IndexBackward w idx (fromVBit <$> val) - Right wv ->- do z <- ashr x <$> asWordVal sym wv- return . VWord (toInteger (SBV.intSizeOf x)) . pure . WordVal $ z
src/Cryptol/Eval/Value.hs view
@@ -6,6 +6,7 @@ -- Stability : provisional -- Portability : portable +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-}@@ -16,7 +17,6 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternGuards #-}-{-# LANGUAGE Safe #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TupleSections #-}@@ -26,7 +26,6 @@ module Cryptol.Eval.Value ( -- * GenericValue GenValue(..)- , forceWordValue , forceValue , Backend(..) , asciiMode@@ -39,9 +38,6 @@ , tlam , nlam , ilam- , toStream- , toFinSeq- , toSeq , mkSeq -- ** Value eliminators , fromVBit@@ -64,59 +60,32 @@ -- ** Pretty printing , defaultPPOpts , ppValue-- -- * Sequence Maps- , SeqMap (..)- , lookupSeqMap- , finiteSeqMap- , infiniteSeqMap- , enumerateSeqMap- , streamSeqMap- , reverseSeqMap- , updateSeqMap- , dropSeqMap- , concatSeqMap- , splitSeqMap- , memoMap- , zipSeqMap- , mapSeqMap- , largeBitSize- -- * WordValue- , WordValue(..)- , asWordVal- , asBitsMap- , enumerateWordValue- , enumerateWordValueRev- , wordValueSize- , indexWordValue- , updateWordValue+ -- * Merge and if/then/else+ , iteValue+ , mergeValue ) where -import Control.Monad.IO.Class-import Data.Bits-import Data.IORef-import Data.Map.Strict (Map) import Data.Ratio-import qualified Data.Map.Strict as Map-import MonadLib import Numeric (showIntAtBase) import Cryptol.Backend+import Cryptol.Backend.SeqMap import qualified Cryptol.Backend.Arch as Arch import Cryptol.Backend.Monad ( evalPanic, wordTooWide, CallStack, combineCallStacks ) import Cryptol.Backend.FloatHelpers (fpPP)+import Cryptol.Backend.WordValue+ import Cryptol.Eval.Type import Cryptol.TypeCheck.Solver.InfNat(Nat'(..))+ import Cryptol.Utils.Ident (Ident) import Cryptol.Utils.Logger(Logger) import Cryptol.Utils.Panic(panic) import Cryptol.Utils.PP import Cryptol.Utils.RecordMap -import Data.List(genericIndex)- import GHC.Generics (Generic) -- | Some options for evalutaion@@ -127,186 +96,6 @@ -- Values ---------------------------------------------------------------------- --- | A sequence map represents a mapping from nonnegative integer indices--- to values. These are used to represent both finite and infinite sequences.-data SeqMap sym- = IndexSeqMap !(Integer -> SEval sym (GenValue sym))- | UpdateSeqMap !(Map Integer (SEval sym (GenValue sym)))- !(Integer -> SEval sym (GenValue sym))--lookupSeqMap :: SeqMap sym -> Integer -> SEval sym (GenValue sym)-lookupSeqMap (IndexSeqMap f) i = f i-lookupSeqMap (UpdateSeqMap m f) i =- case Map.lookup i m of- Just x -> x- Nothing -> f i---- | An arbitrarily-chosen number of elements where we switch from a dense--- sequence representation of bit-level words to 'SeqMap' representation.-largeBitSize :: Integer-largeBitSize = 1 `shiftL` 48---- | Generate a finite sequence map from a list of values-finiteSeqMap :: [SEval sym (GenValue sym)] -> SeqMap sym-finiteSeqMap xs =- UpdateSeqMap- (Map.fromList (zip [0..] xs))- (\i -> panic "finiteSeqMap" ["Out of bounds access of finite seq map", "length: " ++ show (length xs), show i])---- | Generate an infinite sequence map from a stream of values-infiniteSeqMap :: Backend sym => sym -> [SEval sym (GenValue sym)] -> SEval sym (SeqMap sym)-infiniteSeqMap sym xs =- -- TODO: use an int-trie?- memoMap sym (IndexSeqMap $ \i -> genericIndex xs i)---- | Create a finite list of length @n@ of the values from @[0..n-1]@ in--- the given the sequence emap.-enumerateSeqMap :: (Integral n) => n -> SeqMap sym -> [SEval sym (GenValue sym)]-enumerateSeqMap n m = [ lookupSeqMap m i | i <- [0 .. (toInteger n)-1] ]---- | Create an infinite stream of all the values in a sequence map-streamSeqMap :: SeqMap sym -> [SEval sym (GenValue sym)]-streamSeqMap m = [ lookupSeqMap m i | i <- [0..] ]---- | Reverse the order of a finite sequence map-reverseSeqMap :: Integer -- ^ Size of the sequence map- -> SeqMap sym- -> SeqMap sym-reverseSeqMap n vals = IndexSeqMap $ \i -> lookupSeqMap vals (n - 1 - i)--updateSeqMap :: SeqMap sym -> Integer -> SEval sym (GenValue sym) -> SeqMap sym-updateSeqMap (UpdateSeqMap m sm) i x = UpdateSeqMap (Map.insert i x m) sm-updateSeqMap (IndexSeqMap f) i x = UpdateSeqMap (Map.singleton i x) f---- | Concatenate the first @n@ values of the first sequence map onto the--- beginning of the second sequence map.-concatSeqMap :: Integer -> SeqMap sym -> SeqMap sym -> SeqMap sym-concatSeqMap n x y =- IndexSeqMap $ \i ->- if i < n- then lookupSeqMap x i- else lookupSeqMap y (i-n)---- | Given a number @n@ and a sequence map, return two new sequence maps:--- the first containing the values from @[0..n-1]@ and the next containing--- the values from @n@ onward.-splitSeqMap :: Integer -> SeqMap sym -> (SeqMap sym, SeqMap sym)-splitSeqMap n xs = (hd,tl)- where- hd = xs- tl = IndexSeqMap $ \i -> lookupSeqMap xs (i+n)---- | Drop the first @n@ elements of the given 'SeqMap'.-dropSeqMap :: Integer -> SeqMap sym -> SeqMap sym-dropSeqMap 0 xs = xs-dropSeqMap n xs = IndexSeqMap $ \i -> lookupSeqMap xs (i+n)---- | Given a sequence map, return a new sequence map that is memoized using--- a finite map memo table.-memoMap :: Backend sym => sym -> SeqMap sym -> SEval sym (SeqMap sym)-memoMap sym x = do- stk <- sGetCallStack sym- cache <- liftIO $ newIORef $ Map.empty- return $ IndexSeqMap (memo cache stk)-- where- memo cache stk i = do- mz <- liftIO (Map.lookup i <$> readIORef cache)- case mz of- Just z -> return z- Nothing -> sWithCallStack sym stk (doEval cache i)-- doEval cache i = do- v <- lookupSeqMap x i- liftIO $ atomicModifyIORef' cache (\m -> (Map.insert i v m, ()))- return v---- | Apply the given evaluation function pointwise to the two given--- sequence maps.-zipSeqMap ::- Backend sym =>- sym ->- (GenValue sym -> GenValue sym -> SEval sym (GenValue sym)) ->- SeqMap sym ->- SeqMap sym ->- SEval sym (SeqMap sym)-zipSeqMap sym f x y =- memoMap sym (IndexSeqMap $ \i -> join (f <$> lookupSeqMap x i <*> lookupSeqMap y i))---- | Apply the given function to each value in the given sequence map-mapSeqMap ::- Backend sym =>- sym ->- (GenValue sym -> SEval sym (GenValue sym)) ->- SeqMap sym -> SEval sym (SeqMap sym)-mapSeqMap sym f x =- memoMap sym (IndexSeqMap $ \i -> f =<< lookupSeqMap x i)---- | For efficiency reasons, we handle finite sequences of bits as special cases--- in the evaluator. In cases where we know it is safe to do so, we prefer to--- used a "packed word" representation of bit sequences. This allows us to rely--- directly on Integer types (in the concrete evaluator) and SBV's Word types (in--- the symbolic simulator).------ However, if we cannot be sure all the bits of the sequence--- will eventually be forced, we must instead rely on an explicit sequence of bits--- representation.-data WordValue sym- = WordVal !(SWord sym) -- ^ Packed word representation for bit sequences.- | LargeBitsVal !Integer !(SeqMap sym) -- ^ A large bitvector sequence, represented as a- -- 'SeqMap' of bits.- deriving (Generic)---- | Force a word value into packed word form-asWordVal :: Backend sym => sym -> WordValue sym -> SEval sym (SWord sym)-asWordVal _ (WordVal w) = return w-asWordVal sym (LargeBitsVal n xs) = packWord sym =<< traverse (fromVBit <$>) (enumerateSeqMap n xs)---- | Force a word value into a sequence of bits-asBitsMap :: Backend sym => sym -> WordValue sym -> SeqMap sym-asBitsMap sym (WordVal w) = IndexSeqMap $ \i -> VBit <$> (wordBit sym w i)-asBitsMap _ (LargeBitsVal _ xs) = xs---- | Turn a word value into a sequence of bits, forcing each bit.--- The sequence is returned in big-endian order.-enumerateWordValue :: Backend sym => sym -> WordValue sym -> SEval sym [SBit sym]-enumerateWordValue sym (WordVal w) = unpackWord sym w-enumerateWordValue _ (LargeBitsVal n xs) = traverse (fromVBit <$>) (enumerateSeqMap n xs)---- | Turn a word value into a sequence of bits, forcing each bit.--- The sequence is returned in reverse of the usual order, which is little-endian order.-enumerateWordValueRev :: Backend sym => sym -> WordValue sym -> SEval sym [SBit sym]-enumerateWordValueRev sym (WordVal w) = reverse <$> unpackWord sym w-enumerateWordValueRev _ (LargeBitsVal n xs) = traverse (fromVBit <$>) (enumerateSeqMap n (reverseSeqMap n xs))---- | Compute the size of a word value-wordValueSize :: Backend sym => sym -> WordValue sym -> Integer-wordValueSize sym (WordVal w) = wordLen sym w-wordValueSize _ (LargeBitsVal n _) = n---- | Select an individual bit from a word value-indexWordValue :: Backend sym => sym -> WordValue sym -> Integer -> SEval sym (SBit sym)-indexWordValue sym (WordVal w) idx- | 0 <= idx && idx < wordLen sym w = wordBit sym w idx- | otherwise = invalidIndex sym idx-indexWordValue sym (LargeBitsVal n xs) idx- | 0 <= idx && idx < n = fromVBit <$> lookupSeqMap xs idx- | otherwise = invalidIndex sym idx---- | Produce a new 'WordValue' from the one given by updating the @i@th bit with the--- given bit value.-updateWordValue :: Backend sym =>- sym -> WordValue sym -> Integer -> SEval sym (SBit sym) -> SEval sym (WordValue sym)-updateWordValue sym (WordVal w) idx b- | idx < 0 || idx >= wordLen sym w = invalidIndex sym idx- | isReady sym b = WordVal <$> (wordUpdate sym w idx =<< b)--updateWordValue sym wv idx b- | 0 <= idx && idx < wordValueSize sym wv =- pure $ LargeBitsVal (wordValueSize sym wv) $ updateSeqMap (asBitsMap sym wv) idx (VBit <$> b)- | otherwise = invalidIndex sym idx-- -- | Generic value type, parameterized by bit and word types. -- -- NOTE: we maintain an important invariant regarding sequence types.@@ -320,21 +109,16 @@ | VInteger !(SInteger sym) -- ^ @ Integer @ or @ Z n @ | VRational !(SRational sym) -- ^ @ Rational @ | VFloat !(SFloat sym)- | VSeq !Integer !(SeqMap sym) -- ^ @ [n]a @+ | VSeq !Integer !(SeqMap sym (GenValue sym)) -- ^ @ [n]a @ -- Invariant: VSeq is never a sequence of bits- | VWord !Integer !(SEval sym (WordValue sym)) -- ^ @ [n]Bit @- | VStream !(SeqMap sym) -- ^ @ [inf]a @+ | VWord !Integer !(WordValue sym) -- ^ @ [n]Bit @+ | VStream !(SeqMap sym (GenValue sym)) -- ^ @ [inf]a @ | VFun CallStack (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -- ^ functions | VPoly CallStack (TValue -> SEval sym (GenValue sym)) -- ^ polymorphic values (kind *) | VNumPoly CallStack (Nat' -> SEval sym (GenValue sym)) -- ^ polymorphic values (kind #) deriving Generic --- | Force the evaluation of a word value-forceWordValue :: Backend sym => WordValue sym -> SEval sym ()-forceWordValue (WordVal w) = seq w (return ())-forceWordValue (LargeBitsVal n xs) = mapM_ (\x -> const () <$> x) (enumerateSeqMap n xs)- -- | Force the evaluation of a value forceValue :: Backend sym => GenValue sym -> SEval sym () forceValue v = case v of@@ -345,7 +129,7 @@ VInteger i -> seq i (return ()) VRational q -> seq q (return ()) VFloat f -> seq f (return ())- VWord _ wv -> forceWordValue =<< wv+ VWord _ wv -> forceWordValue wv VStream _ -> return () VFun{} -> return () VPoly{} -> return ()@@ -353,7 +137,7 @@ -instance Backend sym => Show (GenValue sym) where+instance Show (GenValue sym) where show v = case v of VRecord fs -> "record:" ++ show (displayOrder fs) VTuple xs -> "tuple:" ++ show (length xs)@@ -368,7 +152,6 @@ VPoly{} -> "poly" VNumPoly{} -> "numpoly" - -- Pretty Printing ------------------------------------------------------------- ppValue :: forall sym.@@ -382,30 +165,32 @@ loop :: GenValue sym -> SEval sym Doc loop val = case val of VRecord fs -> do fs' <- traverse (>>= loop) fs- return $ braces (sep (punctuate comma (map ppField (displayFields fs'))))+ return $ ppRecord (map ppField (fields fs')) where ppField (f,r) = pp f <+> char '=' <+> r VTuple vals -> do vals' <- traverse (>>=loop) vals- return $ parens (sep (punctuate comma vals'))+ return $ ppTuple vals' VBit b -> ppSBit x b VInteger i -> ppSInteger x i VRational q -> ppSRational x q VFloat i -> ppSFloat x opts i VSeq sz vals -> ppWordSeq sz vals- VWord _ wv -> ppWordVal =<< wv+ VWord _ wv -> ppWordVal wv VStream vals -> do vals' <- traverse (>>=loop) $ enumerateSeqMap (useInfLength opts) vals- return $ brackets $ fsep- $ punctuate comma- ( vals' ++ [text "..."]- )+ return $ ppList ( vals' ++ [text "..."] ) VFun{} -> return $ text "<function>" VPoly{} -> return $ text "<polymorphic value>" VNumPoly{} -> return $ text "<polymorphic value>" + fields :: RecordMap Ident Doc -> [(Ident, Doc)]+ fields = case useFieldOrder opts of+ DisplayOrder -> displayFields+ CanonicalOrder -> canonicalFields+ ppWordVal :: WordValue sym -> SEval sym Doc ppWordVal w = ppSWord x opts =<< asWordVal x w - ppWordSeq :: Integer -> SeqMap sym -> SEval sym Doc+ ppWordSeq :: Integer -> SeqMap sym (GenValue sym) -> SEval sym Doc ppWordSeq sz vals = do ws <- sequence (enumerateSeqMap sz vals) case ws of@@ -416,9 +201,9 @@ case traverse (wordAsChar x) vs of Just str -> return $ text (show str) _ -> do vs' <- mapM (ppSWord x opts) vs- return $ brackets (fsep (punctuate comma vs'))+ return $ ppList vs' _ -> do ws' <- traverse loop ws- return $ brackets (fsep (punctuate comma ws'))+ return $ ppList ws' ppSBit :: Backend sym => sym -> SBit sym -> SEval sym Doc ppSBit sym b =@@ -485,7 +270,7 @@ prefix len = case base of 2 -> text "0b" <.> padding 1 len 8 -> text "0o" <.> padding 3 len- 10 -> empty+ 10 -> mempty 16 -> text "0x" <.> padding 4 len _ -> text "0" <.> char '<' <.> int base <.> char '>' @@ -514,10 +299,10 @@ -- Value Constructors ---------------------------------------------------------- -- | Create a packed word of n bits.-word :: Backend sym => sym -> Integer -> Integer -> GenValue sym+word :: Backend sym => sym -> Integer -> Integer -> SEval sym (GenValue sym) word sym n i | n >= Arch.maxBigIntWidth = wordTooWide n- | otherwise = VWord n (WordVal <$> wordLit sym n i)+ | otherwise = VWord n . wordVal <$> wordLit sym n i -- | Construct a function value@@ -544,36 +329,14 @@ Nat i -> f i Inf -> panic "ilam" [ "Unexpected `inf`" ]) --- | Generate a stream.-toStream :: Backend sym => sym -> [GenValue sym] -> SEval sym (GenValue sym)-toStream sym vs =- VStream <$> infiniteSeqMap sym (map pure vs)--toFinSeq ::- Backend sym =>- sym -> Integer -> TValue -> [GenValue sym] -> GenValue sym-toFinSeq sym len elty vs- | isTBit elty = VWord len (WordVal <$> packWord sym (map fromVBit vs))- | otherwise = VSeq len $ finiteSeqMap (map pure vs)- -- | Construct either a finite sequence, or a stream. In the finite case, -- record whether or not the elements were bits, to aid pretty-printing.-toSeq ::- Backend sym =>- sym -> Nat' -> TValue -> [GenValue sym] -> SEval sym (GenValue sym)-toSeq sym len elty vals = case len of- Nat n -> return $ toFinSeq sym n elty vals- Inf -> toStream sym vals----- | Construct either a finite sequence, or a stream. In the finite case,--- record whether or not the elements were bits, to aid pretty-printing.-mkSeq :: Backend sym => Nat' -> TValue -> SeqMap sym -> GenValue sym-mkSeq len elty vals = case len of+mkSeq :: Backend sym => sym -> Nat' -> TValue -> SeqMap sym (GenValue sym) -> SEval sym (GenValue sym)+mkSeq sym len elty vals = case len of Nat n- | isTBit elty -> VWord n $ pure $ LargeBitsVal n vals- | otherwise -> VSeq n vals- Inf -> VStream vals+ | isTBit elty -> VWord n <$> bitmapWordVal sym n (fromVBit <$> vals)+ | otherwise -> pure $ VSeq n vals+ Inf -> pure $ VStream vals -- Value Destructors -----------------------------------------------------------@@ -582,47 +345,47 @@ fromVBit :: GenValue sym -> SBit sym fromVBit val = case val of VBit b -> b- _ -> evalPanic "fromVBit" ["not a Bit"]+ _ -> evalPanic "fromVBit" ["not a Bit", show val] -- | Extract an integer value. fromVInteger :: GenValue sym -> SInteger sym fromVInteger val = case val of VInteger i -> i- _ -> evalPanic "fromVInteger" ["not an Integer"]+ _ -> evalPanic "fromVInteger" ["not an Integer", show val] -- | Extract a rational value. fromVRational :: GenValue sym -> SRational sym fromVRational val = case val of VRational q -> q- _ -> evalPanic "fromVRational" ["not a Rational"]+ _ -> evalPanic "fromVRational" ["not a Rational", show val] -- | Extract a finite sequence value.-fromVSeq :: GenValue sym -> SeqMap sym+fromVSeq :: GenValue sym -> SeqMap sym (GenValue sym) fromVSeq val = case val of VSeq _ vs -> vs- _ -> evalPanic "fromVSeq" ["not a sequence"]+ _ -> evalPanic "fromVSeq" ["not a sequence", show val] -- | Extract a sequence.-fromSeq :: Backend sym => String -> GenValue sym -> SEval sym (SeqMap sym)+fromSeq :: Backend sym => String -> GenValue sym -> SEval sym (SeqMap sym (GenValue sym)) fromSeq msg val = case val of VSeq _ vs -> return vs VStream vs -> return vs- _ -> evalPanic "fromSeq" ["not a sequence", msg]+ _ -> evalPanic "fromSeq" ["not a sequence", msg, show val] -fromWordVal :: Backend sym => String -> GenValue sym -> SEval sym (WordValue sym)+fromWordVal :: Backend sym => String -> GenValue sym -> WordValue sym fromWordVal _msg (VWord _ wval) = wval-fromWordVal msg _ = evalPanic "fromWordVal" ["not a word value", msg]+fromWordVal msg val = evalPanic "fromWordVal" ["not a word value", msg, show val] asIndex :: Backend sym =>- sym -> String -> TValue -> GenValue sym -> SEval sym (Either (SInteger sym) (WordValue sym))-asIndex _sym _msg TVInteger (VInteger i) = pure (Left i)-asIndex _sym _msg _ (VWord _ wval) = Right <$> wval-asIndex _sym msg _ _ = evalPanic "asIndex" ["not an index value", msg]+ sym -> String -> TValue -> GenValue sym -> Either (SInteger sym) (WordValue sym)+asIndex _sym _msg TVInteger (VInteger i) = Left i+asIndex _sym _msg _ (VWord _ wval) = Right wval+asIndex _sym msg _ val = evalPanic "asIndex" ["not an index value", msg, show val] -- | Extract a packed word. fromVWord :: Backend sym => sym -> String -> GenValue sym -> SEval sym (SWord sym)-fromVWord sym _msg (VWord _ wval) = wval >>= asWordVal sym-fromVWord _ msg _ = evalPanic "fromVWord" ["not a word", msg]+fromVWord sym _msg (VWord _ wval) = asWordVal sym wval+fromVWord _ msg val = evalPanic "fromVWord" ["not a word", msg, show val] vWordLen :: Backend sym => GenValue sym -> Maybe Integer vWordLen val = case val of@@ -632,55 +395,119 @@ -- | If the given list of values are all fully-evaluated thunks -- containing bits, return a packed word built from the same bits. -- However, if any value is not a fully-evaluated bit, return 'Nothing'.-tryFromBits :: Backend sym => sym -> [SEval sym (GenValue sym)] -> Maybe (SEval sym (SWord sym))+tryFromBits :: Backend sym => sym -> [SEval sym (GenValue sym)] -> SEval sym (Maybe (SWord sym)) tryFromBits sym = go id where- go f [] = Just (packWord sym =<< sequence (f []))- go f (v : vs) | isReady sym v = go (f . ((fromVBit <$> v):)) vs- go _ (_ : _) = Nothing+ go f [] = Just <$> (packWord sym (f []))+ go f (v : vs) =+ isReady sym v >>= \case+ Just v' -> go (f . ((fromVBit v'):)) vs+ Nothing -> pure Nothing -- | Extract a function from a value. fromVFun :: Backend sym => sym -> GenValue sym -> (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) fromVFun sym val = case val of VFun fnstk f -> \x -> sModifyCallStack sym (\stk -> combineCallStacks stk fnstk) (f x)- _ -> evalPanic "fromVFun" ["not a function"]+ _ -> evalPanic "fromVFun" ["not a function", show val] -- | Extract a polymorphic function from a value. fromVPoly :: Backend sym => sym -> GenValue sym -> (TValue -> SEval sym (GenValue sym)) fromVPoly sym val = case val of VPoly fnstk f -> \x -> sModifyCallStack sym (\stk -> combineCallStacks stk fnstk) (f x)- _ -> evalPanic "fromVPoly" ["not a polymorphic value"]+ _ -> evalPanic "fromVPoly" ["not a polymorphic value", show val] -- | Extract a polymorphic function from a value. fromVNumPoly :: Backend sym => sym -> GenValue sym -> (Nat' -> SEval sym (GenValue sym)) fromVNumPoly sym val = case val of VNumPoly fnstk f -> \x -> sModifyCallStack sym (\stk -> combineCallStacks stk fnstk) (f x)- _ -> evalPanic "fromVNumPoly" ["not a polymorphic value"]+ _ -> evalPanic "fromVNumPoly" ["not a polymorphic value", show val] -- | Extract a tuple from a value. fromVTuple :: GenValue sym -> [SEval sym (GenValue sym)] fromVTuple val = case val of VTuple vs -> vs- _ -> evalPanic "fromVTuple" ["not a tuple"]+ _ -> evalPanic "fromVTuple" ["not a tuple", show val] -- | Extract a record from a value. fromVRecord :: GenValue sym -> RecordMap Ident (SEval sym (GenValue sym)) fromVRecord val = case val of VRecord fs -> fs- _ -> evalPanic "fromVRecord" ["not a record"]+ _ -> evalPanic "fromVRecord" ["not a record", show val] fromVFloat :: GenValue sym -> SFloat sym fromVFloat val = case val of VFloat x -> x- _ -> evalPanic "fromVFloat" ["not a Float"]+ _ -> evalPanic "fromVFloat" ["not a Float", show val] -- | Lookup a field in a record. lookupRecord :: Ident -> GenValue sym -> SEval sym (GenValue sym) lookupRecord f val = case lookupField f (fromVRecord val) of Just x -> x- Nothing -> evalPanic "lookupRecord" ["malformed record"]+ Nothing -> evalPanic "lookupRecord" ["malformed record", show val]+++-- Merge and if/then/else++{-# INLINE iteValue #-}+iteValue :: Backend sym =>+ sym ->+ SBit sym ->+ SEval sym (GenValue sym) ->+ SEval sym (GenValue sym) ->+ SEval sym (GenValue sym)+iteValue sym b x y+ | Just True <- bitAsLit sym b = x+ | Just False <- bitAsLit sym b = y+ | otherwise = mergeValue' sym b x y++{-# INLINE mergeValue' #-}+mergeValue' :: Backend sym =>+ sym ->+ SBit sym ->+ SEval sym (GenValue sym) ->+ SEval sym (GenValue sym) ->+ SEval sym (GenValue sym)+mergeValue' sym = mergeEval sym (mergeValue sym)++mergeValue :: Backend sym =>+ sym ->+ SBit sym ->+ GenValue sym ->+ GenValue sym ->+ SEval sym (GenValue sym)+mergeValue sym c v1 v2 =+ case (v1, v2) of+ (VRecord fs1 , VRecord fs2 ) ->+ do let res = zipRecords (\_lbl -> mergeValue' sym c) fs1 fs2+ case res of+ Left f -> panic "Cryptol.Eval.Value" [ "mergeValue: incompatible record values", show f ]+ Right r -> pure (VRecord r)+ (VTuple vs1 , VTuple vs2 ) | length vs1 == length vs2 ->+ pure $ VTuple $ zipWith (mergeValue' sym c) vs1 vs2+ (VBit b1 , VBit b2 ) -> VBit <$> iteBit sym c b1 b2+ (VInteger i1 , VInteger i2 ) -> VInteger <$> iteInteger sym c i1 i2+ (VRational q1, VRational q2) -> VRational <$> iteRational sym c q1 q2+ (VFloat f1 , VFloat f2) -> VFloat <$> iteFloat sym c f1 f2+ (VWord n1 w1 , VWord n2 w2 ) | n1 == n2 -> VWord n1 <$> mergeWord sym c w1 w2+ (VSeq n1 vs1 , VSeq n2 vs2 ) | n1 == n2 -> VSeq n1 <$> memoMap sym (Nat n1) (mergeSeqMapVal sym c vs1 vs2)+ (VStream vs1 , VStream vs2 ) -> VStream <$> memoMap sym Inf (mergeSeqMapVal sym c vs1 vs2)+ (f1@VFun{} , f2@VFun{} ) -> lam sym $ \x -> mergeValue' sym c (fromVFun sym f1 x) (fromVFun sym f2 x)+ (f1@VPoly{} , f2@VPoly{} ) -> tlam sym $ \x -> mergeValue' sym c (fromVPoly sym f1 x) (fromVPoly sym f2 x)+ (_ , _ ) -> panic "Cryptol.Eval.Value"+ [ "mergeValue: incompatible values", show v1, show v2 ]++{-# INLINE mergeSeqMapVal #-}+mergeSeqMapVal :: Backend sym =>+ sym ->+ SBit sym ->+ SeqMap sym (GenValue sym)->+ SeqMap sym (GenValue sym)->+ SeqMap sym (GenValue sym)+mergeSeqMapVal sym c x y =+ indexSeqMap $ \i ->+ iteValue sym c (lookupSeqMap x i) (lookupSeqMap y i)
src/Cryptol/Eval/What4.hs view
@@ -24,7 +24,7 @@ import Control.Concurrent.MVar import Control.Monad (foldM) import Control.Monad.IO.Class-import Data.Bits+ import qualified Data.Map as Map import qualified Data.Set as Set import Data.Text (Text)@@ -40,6 +40,8 @@ import Cryptol.Backend import Cryptol.Backend.Monad ( EvalError(..), Unsupported(..) )+import Cryptol.Backend.SeqMap+import Cryptol.Backend.WordValue import Cryptol.Backend.What4 import Cryptol.Eval.Generic@@ -47,9 +49,10 @@ import Cryptol.Eval.Type (TValue(..)) import Cryptol.Eval.Value + import qualified Cryptol.SHA as SHA -import Cryptol.TypeCheck.Solver.InfNat( Nat'(..), widthInteger )+import Cryptol.TypeCheck.Solver.InfNat( Nat'(..) ) import Cryptol.Utils.Ident import Cryptol.Utils.Panic@@ -60,7 +63,6 @@ -- See also Cryptol.Prims.Eval.primTable primTable :: W4.IsSymExprBuilder sym => What4 sym -> IO EvalOpts -> Map.Map PrimIdent (Prim (What4 sym)) primTable sym getEOpts =- let w4sym = w4 sym in Map.union (suiteBPrims sym) $ Map.union (primeECPrims sym) $ Map.union (genericFloatTable sym) $@@ -68,25 +70,9 @@ Map.fromList $ map (\(n, v) -> (prelPrim n, v)) - [ (">>$" , sshrV sym)-- -- Shifts and rotates- , ("<<" , logicShift sym "<<" shiftShrink- (w4bvShl w4sym) (w4bvLshr w4sym)- shiftLeftReindex shiftRightReindex)- , (">>" , logicShift sym ">>" shiftShrink- (w4bvLshr w4sym) (w4bvShl w4sym)- shiftRightReindex shiftLeftReindex)- , ("<<<" , logicShift sym "<<<" rotateShrink- (w4bvRol w4sym) (w4bvRor w4sym)- rotateLeftReindex rotateRightReindex)- , (">>>" , logicShift sym ">>>" rotateShrink- (w4bvRor w4sym) (w4bvRol w4sym)- rotateRightReindex rotateLeftReindex)-- -- Indexing and updates- , ("@" , indexPrim sym (indexFront_int sym) (indexFront_bits sym) (indexFront_word sym))- , ("!" , indexPrim sym (indexBack_int sym) (indexBack_bits sym) (indexBack_word sym))+ [ -- Indexing and updates+ ("@" , indexPrim sym IndexForward (indexFront_int sym) (indexFront_segs sym))+ , ("!" , indexPrim sym IndexBackward (indexFront_int sym) (indexFront_segs sym)) , ("update" , updatePrim sym (updateFrontSym_word sym) (updateFrontSym sym)) , ("updateEnd" , updatePrim sym (updateBackSym_word sym) (updateBackSym sym))@@ -235,7 +221,7 @@ fn <- liftIO $ getUninterpFn sym ("AESKeyExpand" <> Text.pack (show k)) args (W4.BaseStructRepr ret) z <- liftIO $ W4.applySymFn (w4 sym) fn ws -- compute a sequence that projects the relevant fields from the outout tuple- pure $ VSeq (4*(k+7)) $ IndexSeqMap $ \i ->+ pure $ VSeq (4*(k+7)) $ indexSeqMap $ \i -> case intIndex (fromInteger i) (size ret) of Just (Some idx) | Just W4.Refl <- W4.testEquality (ret!idx) (W4.BaseBVRepr (W4.knownNat @32)) -> fromWord32 =<< liftIO (W4.structField (w4 sym) z idx)@@ -250,7 +236,7 @@ addUninterpWarning sym "SHA-224" initSt <- liftIO (mkSHA256InitialState sym SHA.initialSHA224State) finalSt <- foldM (\st blk -> processSHA256Block sym st =<< blk) initSt blks- pure $ VSeq 7 $ IndexSeqMap \i ->+ pure $ VSeq 7 $ indexSeqMap \i -> case intIndex (fromInteger i) (knownSize :: Size SHA256State) of Just (Some idx) -> do z <- liftIO $ W4.structField (w4 sym) finalSt idx@@ -268,7 +254,7 @@ addUninterpWarning sym "SHA-256" initSt <- liftIO (mkSHA256InitialState sym SHA.initialSHA256State) finalSt <- foldM (\st blk -> processSHA256Block sym st =<< blk) initSt blks- pure $ VSeq 8 $ IndexSeqMap \i ->+ pure $ VSeq 8 $ indexSeqMap \i -> case intIndex (fromInteger i) (knownSize :: Size SHA256State) of Just (Some idx) -> do z <- liftIO $ W4.structField (w4 sym) finalSt idx@@ -286,7 +272,7 @@ addUninterpWarning sym "SHA-384" initSt <- liftIO (mkSHA512InitialState sym SHA.initialSHA384State) finalSt <- foldM (\st blk -> processSHA512Block sym st =<< blk) initSt blks- pure $ VSeq 6 $ IndexSeqMap \i ->+ pure $ VSeq 6 $ indexSeqMap \i -> case intIndex (fromInteger i) (knownSize :: Size SHA512State) of Just (Some idx) -> do z <- liftIO $ W4.structField (w4 sym) finalSt idx@@ -304,7 +290,7 @@ addUninterpWarning sym "SHA-512" initSt <- liftIO (mkSHA512InitialState sym SHA.initialSHA512State) finalSt <- foldM (\st blk -> processSHA512Block sym st =<< blk) initSt blks- pure $ VSeq 8 $ IndexSeqMap \i ->+ pure $ VSeq 8 $ indexSeqMap \i -> case intIndex (fromInteger i) (knownSize :: Size SHA512State) of Just (Some idx) -> do z <- liftIO $ W4.structField (w4 sym) finalSt idx@@ -459,7 +445,7 @@ ] toWord32 :: W4.IsSymExprBuilder sym =>- What4 sym -> String -> SeqMap (What4 sym) -> Integer -> SEval (What4 sym) (W4.SymBV sym 32)+ What4 sym -> String -> SeqMap (What4 sym) (GenValue (What4 sym)) -> Integer -> SEval (What4 sym) (W4.SymBV sym 32) toWord32 sym nm ss i = do x <- fromVWord sym nm =<< lookupSeqMap ss i case x of@@ -467,11 +453,10 @@ _ -> panic nm ["Unexpected word size", show (SW.bvWidth x)] fromWord32 :: W4.IsSymExprBuilder sym => W4.SymBV sym 32 -> SEval (What4 sym) (Value sym)-fromWord32 = pure . VWord 32 . pure . WordVal . SW.DBV-+fromWord32 = pure . VWord 32 . wordVal . SW.DBV toWord64 :: W4.IsSymExprBuilder sym =>- What4 sym -> String -> SeqMap (What4 sym) -> Integer -> SEval (What4 sym) (W4.SymBV sym 64)+ What4 sym -> String -> SeqMap (What4 sym) (GenValue (What4 sym)) -> Integer -> SEval (What4 sym) (W4.SymBV sym 64) toWord64 sym nm ss i = do x <- fromVWord sym nm =<< lookupSeqMap ss i case x of@@ -479,7 +464,7 @@ _ -> panic nm ["Unexpected word size", show (SW.bvWidth x)] fromWord64 :: W4.IsSymExprBuilder sym => W4.SymBV sym 64 -> SEval (What4 sym) (Value sym)-fromWord64 = pure . VWord 64 . pure . WordVal . SW.DBV+fromWord64 = pure . VWord 64 . wordVal . SW.DBV @@ -496,7 +481,7 @@ w3 <- toWord32 sym nm ss 3 fn <- liftIO $ getUninterpFn sym funNm argCtx (W4.BaseStructRepr argCtx) z <- liftIO $ W4.applySymFn (w4 sym) fn (Empty :> w0 :> w1 :> w2 :> w3)- pure $ VSeq 4 $ IndexSeqMap \i ->+ pure $ VSeq 4 $ indexSeqMap \i -> if | i == 0 -> fromWord32 =<< liftIO (W4.structField (w4 sym) z (natIndex @0)) | i == 1 -> fromWord32 =<< liftIO (W4.structField (w4 sym) z (natIndex @1)) | i == 2 -> fromWord32 =<< liftIO (W4.structField (w4 sym) z (natIndex @2))@@ -511,34 +496,12 @@ argCtx = W4.knownRepr -sshrV :: W4.IsSymExprBuilder sym => What4 sym -> Prim (What4 sym)-sshrV sym =- PFinPoly \n ->- PTyPoly \ix ->- PWordFun \x ->- PStrict \y ->- PPrim $- asIndex sym ">>$" ix y >>= \case- Left i ->- do pneg <- intLessThan sym i =<< integerLit sym 0- zneg <- do i' <- shiftShrink sym (Nat n) ix =<< intNegate sym i- amt <- wordFromInt sym n i'- w4bvShl (w4 sym) x amt- zpos <- do i' <- shiftShrink sym (Nat n) ix i- amt <- wordFromInt sym n i'- w4bvAshr (w4 sym) x amt- return (VWord (SW.bvWidth x) (WordVal <$> iteWord sym pneg zneg zpos))-- Right wv ->- do amt <- asWordVal sym wv- return (VWord (SW.bvWidth x) (WordVal <$> w4bvAshr (w4 sym) x amt))- indexFront_int :: W4.IsSymExprBuilder sym => What4 sym -> Nat' -> TValue ->- SeqMap (What4 sym) ->+ SeqMap (What4 sym) (GenValue (What4 sym)) -> TValue -> SInteger (What4 sym) -> SEval (What4 sym) (Value sym)@@ -547,7 +510,9 @@ = lookupSeqMap xs i | (lo, Just hi) <- bounds- = foldr f def [lo .. hi]+ = case foldr f Nothing [lo .. hi] of+ Nothing -> raiseError sym (InvalidIndex Nothing)+ Just m -> m | otherwise = liftIO (X.throw (UnsupportedSymbolicOp "unbounded integer indexing"))@@ -555,11 +520,10 @@ where w4sym = w4 sym - def = raiseError sym (InvalidIndex Nothing)-- f n y =+ f n (Just y) = Just $ do p <- liftIO (W4.intEq w4sym idx =<< W4.intLit w4sym n) iteValue sym p (lookupSeqMap xs n) y+ f n Nothing = Just $ lookupSeqMap xs n bounds = (case W4.rangeLowBound (W4.integerBounds idx) of@@ -581,44 +545,34 @@ (Nat n, _) -> Just n (_ , TVIntMod m) -> Just m _ -> Nothing--indexBack_int ::- W4.IsSymExprBuilder sym =>- What4 sym ->- Nat' ->- TValue ->- SeqMap (What4 sym) ->- TValue ->- SInteger (What4 sym) ->- SEval (What4 sym) (Value sym)-indexBack_int sym (Nat n) a xs ix idx = indexFront_int sym (Nat n) a (reverseSeqMap n xs) ix idx-indexBack_int _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["indexBack_int"]--indexFront_word ::+indexFront_segs :: W4.IsSymExprBuilder sym => What4 sym -> Nat' -> TValue ->- SeqMap (What4 sym) ->+ SeqMap (What4 sym) (GenValue (What4 sym)) -> TValue ->- SWord (What4 sym) ->+ Integer ->+ [IndexSegment (What4 sym)] -> SEval (What4 sym) (Value sym)-indexFront_word sym mblen _a xs _ix idx+indexFront_segs sym mblen _a xs _ix _idx_bits [WordIndexSegment idx] | Just i <- SW.bvAsUnsignedInteger idx = lookupSeqMap xs i | otherwise- = foldr f def idxs+ = case foldr f Nothing idxs of+ Nothing -> raiseError sym (InvalidIndex Nothing)+ Just m -> m where w4sym = w4 sym w = SW.bvWidth idx- def = raiseError sym (InvalidIndex Nothing) - f n y =+ f n (Just y) = Just $ do p <- liftIO (SW.bvEq w4sym idx =<< SW.bvLit w4sym w n) iteValue sym p (lookupSeqMap xs n) y+ f n Nothing = Just $ lookupSeqMap xs n -- maximum possible in-bounds index given the bitwidth -- of the index value and the length of the sequence@@ -635,112 +589,34 @@ Just (lo, hi) -> [lo .. min hi maxIdx] _ -> [0 .. maxIdx] -indexBack_word ::- W4.IsSymExprBuilder sym =>- What4 sym ->- Nat' ->- TValue ->- SeqMap (What4 sym) ->- TValue ->- SWord (What4 sym) ->- SEval (What4 sym) (Value sym)-indexBack_word sym (Nat n) a xs ix idx = indexFront_word sym (Nat n) a (reverseSeqMap n xs) ix idx-indexBack_word _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["indexBack_word"]--indexFront_bits :: forall sym.- W4.IsSymExprBuilder sym =>- What4 sym ->- Nat' ->- TValue ->- SeqMap (What4 sym) ->- TValue ->- [SBit (What4 sym)] ->- SEval (What4 sym) (Value sym)-indexFront_bits sym mblen _a xs _ix bits0 = go 0 (length bits0) bits0- where- go :: Integer -> Int -> [W4.Pred sym] -> W4Eval sym (Value sym)- go i _k []- -- For indices out of range, fail- | Nat n <- mblen- , i >= n- = raiseError sym (InvalidIndex (Just i))-- | otherwise- = lookupSeqMap xs i-- go i k (b:bs)- -- Fail early when all possible indices we could compute from here- -- are out of bounds- | Nat n <- mblen- , (i `shiftL` k) >= n- = raiseError sym (InvalidIndex Nothing)-- | otherwise- = iteValue sym b- (go ((i `shiftL` 1) + 1) (k-1) bs)- (go (i `shiftL` 1) (k-1) bs)--indexBack_bits ::- W4.IsSymExprBuilder sym =>- What4 sym ->- Nat' ->- TValue ->- SeqMap (What4 sym) ->- TValue ->- [SBit (What4 sym)] ->- SEval (What4 sym) (Value sym)-indexBack_bits sym (Nat n) a xs ix idx = indexFront_bits sym (Nat n) a (reverseSeqMap n xs) ix idx-indexBack_bits _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["indexBack_bits"]----- | Compare a symbolic word value with a concrete integer.-wordValueEqualsInteger :: forall sym.- W4.IsSymExprBuilder sym =>- What4 sym ->- WordValue (What4 sym) ->- Integer ->- W4Eval sym (W4.Pred sym)-wordValueEqualsInteger sym wv i- | wordValueSize sym wv < widthInteger i = return (W4.falsePred w4sym)- | otherwise =- case wv of- WordVal w -> liftIO (SW.bvEq w4sym w =<< SW.bvLit w4sym (SW.bvWidth w) i)- _ -> liftIO . bitsAre i =<< enumerateWordValueRev sym wv -- little-endian+indexFront_segs sym mblen _a xs _ix idx_bits segs =+ do xs' <- barrelShifter sym (mergeValue sym) shiftOp mblen xs idx_bits segs+ lookupSeqMap xs' 0 where- w4sym = w4 sym+ shiftOp vs amt = pure (indexSeqMap (\i -> lookupSeqMap vs $! amt+i)) - bitsAre :: Integer -> [W4.Pred sym] -> IO (W4.Pred sym)- bitsAre n [] = pure (W4.backendPred w4sym (n == 0))- bitsAre n (b : bs) =- do pb <- bitIs (testBit n 0) b- pbs <- bitsAre (n `shiftR` 1) bs- W4.andPred w4sym pb pbs - bitIs :: Bool -> W4.Pred sym -> IO (W4.Pred sym)- bitIs b x = if b then pure x else W4.notPred w4sym x- updateFrontSym :: W4.IsSymExprBuilder sym => What4 sym -> Nat' -> TValue ->- SeqMap (What4 sym) ->+ SeqMap (What4 sym) (GenValue (What4 sym)) -> Either (SInteger (What4 sym)) (WordValue (What4 sym)) -> SEval (What4 sym) (Value sym) ->- SEval (What4 sym) (SeqMap (What4 sym))+ SEval (What4 sym) (SeqMap (What4 sym) (GenValue (What4 sym))) updateFrontSym sym _len _eltTy vs (Left idx) val = case W4.asInteger idx of Just i -> return $ updateSeqMap vs i val- Nothing -> return $ IndexSeqMap $ \i ->+ Nothing -> return $ indexSeqMap $ \i -> do b <- intEq sym idx =<< integerLit sym i iteValue sym b val (lookupSeqMap vs i) -updateFrontSym sym _len _eltTy vs (Right wv) val =- case wv of- WordVal w | Just j <- SW.bvAsUnsignedInteger w ->- return $ updateSeqMap vs j val- _ ->- memoMap sym $ IndexSeqMap $ \i ->+updateFrontSym sym len _eltTy vs (Right wv) val =+ wordValAsLit sym wv >>= \case+ Just j -> return $ updateSeqMap vs j val+ Nothing ->+ memoMap sym len $ indexSeqMap $ \i -> do b <- wordValueEqualsInteger sym wv i iteValue sym b val (lookupSeqMap vs i) @@ -749,25 +625,25 @@ What4 sym -> Nat' -> TValue ->- SeqMap (What4 sym) ->+ SeqMap (What4 sym) (GenValue (What4 sym)) -> Either (SInteger (What4 sym)) (WordValue (What4 sym)) -> SEval (What4 sym) (Value sym) ->- SEval (What4 sym) (SeqMap (What4 sym))+ SEval (What4 sym) (SeqMap (What4 sym) (GenValue (What4 sym))) updateBackSym _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["updateBackSym"] updateBackSym sym (Nat n) _eltTy vs (Left idx) val = case W4.asInteger idx of Just i -> return $ updateSeqMap vs (n - 1 - i) val- Nothing -> return $ IndexSeqMap $ \i ->+ Nothing -> return $ indexSeqMap $ \i -> do b <- intEq sym idx =<< integerLit sym (n - 1 - i) iteValue sym b val (lookupSeqMap vs i) updateBackSym sym (Nat n) _eltTy vs (Right wv) val =- case wv of- WordVal w | Just j <- SW.bvAsUnsignedInteger w ->+ wordValAsLit sym wv >>= \case+ Just j -> return $ updateSeqMap vs (n - 1 - j) val- _ ->- memoMap sym $ IndexSeqMap $ \i ->+ Nothing ->+ memoMap sym (Nat n) $ indexSeqMap $ \i -> do b <- wordValueEqualsInteger sym wv (n - 1 - i) iteValue sym b val (lookupSeqMap vs i) @@ -783,36 +659,11 @@ SEval (What4 sym) (WordValue (What4 sym)) updateFrontSym_word _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["updateFrontSym_word"] -updateFrontSym_word sym (Nat _) eltTy (LargeBitsVal n bv) idx val =- LargeBitsVal n <$> updateFrontSym sym (Nat n) eltTy bv idx val--updateFrontSym_word sym (Nat n) eltTy (WordVal bv) (Left idx) val =+updateFrontSym_word sym (Nat n) _eltTy w (Left idx) val = do idx' <- wordFromInt sym n idx- updateFrontSym_word sym (Nat n) eltTy (WordVal bv) (Right (WordVal idx')) val--updateFrontSym_word sym (Nat n) eltTy bv (Right wv) val =- case wv of- WordVal idx- | Just j <- SW.bvAsUnsignedInteger idx ->- updateWordValue sym bv j (fromVBit <$> val)-- | WordVal bw <- bv ->- WordVal <$>- do b <- fromVBit <$> val- let sz = SW.bvWidth bw- highbit <- liftIO (SW.bvLit (w4 sym) sz (bit (fromInteger (sz-1))))- msk <- w4bvLshr (w4 sym) highbit idx- liftIO $- case W4.asConstantPred b of- Just True -> SW.bvOr (w4 sym) bw msk- Just False -> SW.bvAnd (w4 sym) bw =<< SW.bvNot (w4 sym) msk- Nothing ->- do q <- SW.bvFill (w4 sym) sz b- bw' <- SW.bvAnd (w4 sym) bw =<< SW.bvNot (w4 sym) msk- SW.bvXor (w4 sym) bw' =<< SW.bvAnd (w4 sym) q msk-- _ -> LargeBitsVal (wordValueSize sym wv) <$>- updateFrontSym sym (Nat n) eltTy (asBitsMap sym bv) (Right wv) val+ updateWordByWord sym IndexForward w (wordVal idx') (fromVBit <$> val)+updateFrontSym_word sym (Nat _n) _eltTy w (Right idx) val =+ updateWordByWord sym IndexForward w idx (fromVBit <$> val) updateBackSym_word ::@@ -824,35 +675,10 @@ Either (SInteger (What4 sym)) (WordValue (What4 sym)) -> SEval (What4 sym) (GenValue (What4 sym)) -> SEval (What4 sym) (WordValue (What4 sym))-updateBackSym_word _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["updateBackSym_word"]--updateBackSym_word sym (Nat _) eltTy (LargeBitsVal n bv) idx val =- LargeBitsVal n <$> updateBackSym sym (Nat n) eltTy bv idx val+updateBackSym_word _ Inf _ _ _ _ = evalPanic "Expected finite sequence" ["updateFrontSym_word"] -updateBackSym_word sym (Nat n) eltTy (WordVal bv) (Left idx) val =+updateBackSym_word sym (Nat n) _eltTy w (Left idx) val = do idx' <- wordFromInt sym n idx- updateBackSym_word sym (Nat n) eltTy (WordVal bv) (Right (WordVal idx')) val--updateBackSym_word sym (Nat n) eltTy bv (Right wv) val =- case wv of- WordVal idx- | Just j <- SW.bvAsUnsignedInteger idx ->- updateWordValue sym bv (n - 1 - j) (fromVBit <$> val)-- | WordVal bw <- bv ->- WordVal <$>- do b <- fromVBit <$> val- let sz = SW.bvWidth bw- lowbit <- liftIO (SW.bvLit (w4 sym) sz 1)- msk <- w4bvShl (w4 sym) lowbit idx- liftIO $- case W4.asConstantPred b of- Just True -> SW.bvOr (w4 sym) bw msk- Just False -> SW.bvAnd (w4 sym) bw =<< SW.bvNot (w4 sym) msk- Nothing ->- do q <- SW.bvFill (w4 sym) sz b- bw' <- SW.bvAnd (w4 sym) bw =<< SW.bvNot (w4 sym) msk- SW.bvXor (w4 sym) bw' =<< SW.bvAnd (w4 sym) q msk-- _ -> LargeBitsVal (wordValueSize sym wv) <$>- updateBackSym sym (Nat n) eltTy (asBitsMap sym bv) (Right wv) val+ updateWordByWord sym IndexBackward w (wordVal idx') (fromVBit <$> val)+updateBackSym_word sym (Nat _n) _eltTy w (Right idx) val =+ updateWordByWord sym IndexBackward w idx (fromVBit <$> val)
src/Cryptol/F2.hs view
@@ -32,7 +32,7 @@ pmod :: Int -> Integer -> Integer -> Integer-pmod w x m = mask .&. go 0 0 (reduce 1)+pmod w x m = go degree (x .&. mask) (clearBit m degree) where degree :: Int degree = fromInteger (widthInteger m - 1)@@ -43,6 +43,7 @@ mask = bit degree - 1 + -- invariant: z and p are in the range [0..mask] go !i !z !p | i < w = go (i+1) (if testBit x i then z `xor` p else z) (reduce (p `shiftL` 1)) | otherwise = z
src/Cryptol/ModuleSystem.hs view
@@ -29,10 +29,12 @@ , renameType -- * Interfaces- , Iface(..), IfaceParams(..), IfaceDecls(..), genIface+ , Iface, IfaceG(..), IfaceParams(..), IfaceDecls(..), T.genIface , IfaceTySyn, IfaceDecl(..) ) where +import Data.Map (Map)+ import qualified Cryptol.Eval.Concrete as Concrete import Cryptol.ModuleSystem.Env import Cryptol.ModuleSystem.Interface@@ -44,6 +46,7 @@ import Cryptol.Parser.Name (PName) import Cryptol.Parser.NoPat (RemovePatterns) import qualified Cryptol.TypeCheck.AST as T+import qualified Cryptol.TypeCheck.Interface as T import qualified Cryptol.Utils.Ident as M -- Public Interface ------------------------------------------------------------@@ -93,7 +96,7 @@ evalExpr e env = runModuleM env (interactive (Base.evalExpr e)) -- | Typecheck top-level declarations.-checkDecls :: [P.TopDecl PName] -> ModuleCmd (R.NamingEnv,[T.DeclGroup])+checkDecls :: [P.TopDecl PName] -> ModuleCmd (R.NamingEnv,[T.DeclGroup], Map Name T.TySyn) checkDecls ds env = runModuleM env $ interactive $ Base.checkDecls ds@@ -105,10 +108,14 @@ noPat :: RemovePatterns a => a -> ModuleCmd a noPat a env = runModuleM env (interactive (Base.noPat a)) +-- | Rename a *use* of a value name. The distinction between uses and+-- binding is used to keep track of dependencies. renameVar :: R.NamingEnv -> PName -> ModuleCmd Name renameVar names n env = runModuleM env $ interactive $- Base.rename M.interactiveName names (R.renameVar n)+ Base.rename M.interactiveName names (R.renameVar R.NameUse n) +-- | Rename a *use* of a type name. The distinction between uses and+-- binding is used to keep track of dependencies. renameType :: R.NamingEnv -> PName -> ModuleCmd Name renameType names n env = runModuleM env $ interactive $- Base.rename M.interactiveName names (R.renameType n)+ Base.rename M.interactiveName names (R.renameType R.NameUse n)
src/Cryptol/ModuleSystem/Base.hs view
@@ -12,14 +12,38 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ImplicitParams #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-} module Cryptol.ModuleSystem.Base where +import qualified Control.Exception as X+import Control.Monad (unless,when)+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>))+import Data.Text.Encoding (decodeUtf8')+import Data.IORef(newIORef,readIORef)+import System.Directory (doesFileExist, canonicalizePath)+import System.FilePath ( addExtension+ , isAbsolute+ , joinPath+ , (</>)+ , normalise+ , takeDirectory+ , takeFileName+ )+import qualified System.IO.Error as IOE+import qualified Data.Map as Map++import Prelude ()+import Prelude.Compat hiding ( (<>) )+++ import Cryptol.ModuleSystem.Env (DynamicEnv(..)) import Cryptol.ModuleSystem.Fingerprint import Cryptol.ModuleSystem.Interface import Cryptol.ModuleSystem.Monad-import Cryptol.ModuleSystem.Name (Name,liftSupply,PrimMap)+import Cryptol.ModuleSystem.Name (Name,liftSupply,PrimMap,ModPath(..)) import Cryptol.ModuleSystem.Env (lookupModule , LoadedModule(..) , meCoreLint, CoreLint(..)@@ -53,33 +77,21 @@ , suiteBContents, primeECContents, preludeReferenceContents ) import Cryptol.Transform.MonoValues (rewModule) -import qualified Control.Exception as X-import Control.Monad (unless,when)-import Data.Maybe (fromMaybe)-import Data.Monoid ((<>))-import Data.Text.Encoding (decodeUtf8')-import System.Directory (doesFileExist, canonicalizePath)-import System.FilePath ( addExtension- , isAbsolute- , joinPath- , (</>)- , normalise- , takeDirectory- , takeFileName- )-import qualified System.IO.Error as IOE-import qualified Data.Map as Map -import Prelude ()-import Prelude.Compat hiding ( (<>) )-- -- Renaming -------------------------------------------------------------------- rename :: ModName -> R.NamingEnv -> R.RenameM a -> ModuleM a rename modName env m = do+ ifaces <- getIfaces (res,ws) <- liftSupply $ \ supply ->- case R.runRenamer supply modName env m of+ let info = R.RenamerInfo+ { renSupply = supply+ , renContext = TopModule modName+ , renEnv = env+ , renIfaces = ifaces+ }+ in+ case R.runRenamer info m of (Right (a,supply'),ws) -> ((Right a,ws),supply') (Left errs,ws) -> ((Left errs,ws),supply) @@ -89,12 +101,8 @@ Left errs -> renamerErrors errs -- | Rename a module in the context of its imported modules.-renameModule :: P.Module PName- -> ModuleM (IfaceDecls,R.NamingEnv,P.Module Name)-renameModule m = do- (decls,menv) <- importIfaces (map thing (P.mImports m))- (declsEnv,rm) <- rename (thing (mName m)) menv (R.renameModule m)- return (decls,declsEnv,rm)+renameModule :: P.Module PName -> ModuleM R.RenamedModule+renameModule m = rename (thing (mName m)) mempty (R.renameModule m) -- NoPat -----------------------------------------------------------------------@@ -200,15 +208,18 @@ unless quiet $ withLogger logPutStrLn ("Loading module " ++ pretty (P.thing (P.mName pm)))- tcm <- optionalInstantiate =<< checkModule isrc path pm ++ (nameEnv,tcmod) <- checkModule isrc path pm+ tcm <- optionalInstantiate tcmod+ -- 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 tcm+ loadedModule path fp nameEnv tcm return tcm where@@ -231,17 +242,6 @@ fullyQualified :: P.Import -> P.Import fullyQualified i = i { iAs = Just (iModule i) } --- | Find the interface referenced by an import, and generate the naming--- environment that it describes.-importIface :: P.Import -> ModuleM (IfaceDecls,R.NamingEnv)-importIface imp =- do Iface { .. } <- getIface (T.iModule imp)- return (ifPublic, R.interpImport imp ifPublic)---- | Load a series of interfaces, merging their public interfaces.-importIfaces :: [P.Import] -> ModuleM (IfaceDecls,R.NamingEnv)-importIfaces is = mconcat `fmap` mapM importIface is- moduleFile :: ModName -> String -> FilePath moduleFile n = addExtension (joinPath (modNameChunks n)) @@ -299,13 +299,13 @@ addPrelude m | preludeName == P.thing (P.mName m) = m | preludeName `elem` importedMods = m- | otherwise = m { mImports = importPrelude : mImports m }+ | otherwise = m { mDecls = importPrelude : mDecls m } where importedMods = map (P.iModule . P.thing) (P.mImports m)- importPrelude = P.Located+ importPrelude = P.DImport P.Located { P.srcRange = emptyRange , P.thing = P.Import- { iModule = preludeName+ { iModule = P.ImpTop preludeName , iAs = Nothing , iSpec = Nothing }@@ -353,23 +353,20 @@ -- | Typecheck a group of declarations. -- -- INVARIANT: This assumes that NoPat has already been run on the declarations.-checkDecls :: [P.TopDecl PName] -> ModuleM (R.NamingEnv,[T.DeclGroup])+checkDecls :: [P.TopDecl PName] -> ModuleM (R.NamingEnv,[T.DeclGroup], Map.Map Name T.TySyn) checkDecls ds = do fe <- getFocusedEnv let params = mctxParams fe decls = mctxDecls fe names = mctxNames fe - -- introduce names for the declarations before renaming them- declsEnv <- liftSupply (R.namingEnv' (map (R.InModule interactiveName) ds))- rds <- rename interactiveName (declsEnv `R.shadowing` names)- (traverse R.rename ds)-+ (declsEnv,rds) <- rename interactiveName names+ $ R.renameTopDecls interactiveName ds prims <- getPrimMap let act = TCAction { tcAction = T.tcDecls, tcLinter = declsLinter , tcPrims = prims }- ds' <- typecheck act rds params decls- return (declsEnv,ds')+ (ds',tyMap) <- typecheck act rds params decls+ return (declsEnv,ds',tyMap) -- | Generate the primitive map. If the prelude is currently being loaded, this -- should be generated directly from the naming environment given to the renamer@@ -390,12 +387,23 @@ [ "Unable to find the prelude" ] -- | Load a module, be it a normal module or a functor instantiation.-checkModule :: ImportSource -> ModulePath -> P.Module PName -> ModuleM T.Module+checkModule ::+ ImportSource -> ModulePath -> P.Module PName ->+ ModuleM (R.NamingEnv, T.Module) checkModule isrc path m = case P.mInstance m of Nothing -> checkSingleModule T.tcModule isrc path m- Just fmName -> do tf <- getLoaded (thing fmName)- checkSingleModule (T.tcModuleInst tf) isrc path 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 path 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@@ -406,7 +414,7 @@ ImportSource {- ^ why are we loading this -} -> ModulePath {- path -} -> P.Module PName {- ^ module to check -} ->- ModuleM T.Module+ ModuleM (R.NamingEnv,T.Module) checkSingleModule how isrc path m = do -- check that the name of the module matches expectations@@ -432,13 +440,13 @@ npm <- noPat nim -- rename everything- (tcEnv,declsEnv,scm) <- renameModule npm+ renMod <- renameModule npm -- 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. prims <- if thing (mName m) == preludeName- then return (R.toPrimMap declsEnv)+ then return (R.toPrimMap (R.rmDefines renMod)) else getPrimMap -- typecheck@@ -447,11 +455,12 @@ , tcPrims = prims } - tcm0 <- typecheck act scm noIfaceParams tcEnv+ tcm0 <- typecheck act (R.rmModule renMod) noIfaceParams (R.rmImported renMod) let tcm = tcm0 -- fromMaybe tcm0 (addModParams tcm0) - liftSupply (`rewModule` tcm)+ rewMod <- liftSupply (`rewModule` tcm)+ pure (R.rmInScope renMod,rewMod) data TCLinter o = TCLinter { lintCheck ::@@ -473,11 +482,11 @@ , lintModule = Nothing } -declsLinter :: TCLinter [ T.DeclGroup ]+declsLinter :: TCLinter ([ T.DeclGroup ], a) declsLinter = TCLinter- { lintCheck = \ds' i -> case TcSanity.tcDecls i ds' of- Left err -> Left err- Right os -> Right os+ { lintCheck = \(ds',_) i -> case TcSanity.tcDecls i ds' of+ Left err -> Left err+ Right os -> Right os , lintModule = Nothing }@@ -529,16 +538,17 @@ -- | Generate input for the typechecker. genInferInput :: Range -> PrimMap -> IfaceParams -> IfaceDecls -> ModuleM T.InferInput-genInferInput r prims params env = do+genInferInput r prims params env' = do seeds <- getNameSeeds monoBinds <- getMonoBinds- cfg <- getSolverConfig solver <- getTCSolver supply <- getSupply searchPath <- getSearchPath callStacks <- getCallStacks -- TODO: include the environment needed by the module+ let env = flatPublicDecls env'+ -- XXX: we should really just pass this directly return T.InferInput { T.inpRange = r , T.inpVars = Map.map ifDeclSig (ifDecls env)@@ -548,7 +558,6 @@ , T.inpNameSeeds = seeds , T.inpMonoBinds = monoBinds , T.inpCallStacks = callStacks- , T.inpSolverConfig = cfg , T.inpSearchPath = searchPath , T.inpSupply = supply , T.inpPrimNames = prims
src/Cryptol/ModuleSystem/Env.hs view
@@ -11,6 +11,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-} module Cryptol.ModuleSystem.Env where #ifndef RELOCATABLE@@ -24,6 +25,7 @@ import qualified Cryptol.ModuleSystem.NamingEnv as R import Cryptol.Parser.AST import qualified Cryptol.TypeCheck as T+import qualified Cryptol.TypeCheck.Interface as T import qualified Cryptol.TypeCheck.AST as T import Cryptol.Utils.PP (PP(..),text,parens,NameDisp) @@ -31,6 +33,7 @@ import Control.Monad (guard,mplus) import qualified Control.Exception as X import Data.Function (on)+import Data.Set(Set) import Data.Map (Map) import qualified Data.Map as Map import Data.Semigroup@@ -60,9 +63,6 @@ , meNameSeeds :: T.NameSeeds -- ^ A source of new names for the type checker. - , meSolverConfig :: T.SolverConfig- -- ^ Configuration settings for the SMT solver used for type-checking.- , meEvalEnv :: EvalEnv -- ^ The evaluation environment. Contains the values for all loaded -- modules, both public and private.@@ -150,12 +150,6 @@ , meSearchPath = searchPath , meDynEnv = mempty , meMonoBinds = True- , meSolverConfig = T.SolverConfig- { T.solverPath = "z3"- , T.solverArgs = [ "-smt2", "-in" ]- , T.solverVerbose = 0- , T.solverPreludePath = searchPath- } , meCoreLint = NoCoreLint , meSupply = emptySupply }@@ -194,91 +188,79 @@ -- or type check new expressions. data ModContext = ModContext { mctxParams :: IfaceParams+ , mctxExported :: Set Name , mctxDecls :: IfaceDecls+ -- ^ Should contain at least names in NamingEnv, but may have more , mctxNames :: R.NamingEnv+ -- ^ What's in scope inside the module , mctxNameDisp :: NameDisp- , mctxTypeProvenace :: Map Name DeclProvenance- , mctxValueProvenance :: Map Name DeclProvenance } --- | Specifies how a declared name came to be in scope.-data DeclProvenance =- NameIsImportedFrom ModName- | NameIsLocalPublic- | NameIsLocalPrivate- | NameIsParameter- | NameIsDynamicDecl- deriving (Eq,Ord)+-- 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)+ , mctxExported = mctxExported x <> mctxExported y+ , mctxDecls = mctxDecls x <> mctxDecls y+ , mctxNames = names+ , mctxNameDisp = R.toNameDisp names+ } + 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" ] --- | Given the state of the environment, compute information about what's--- in scope on the REPL. This includes what's in the focused module, plus any--- additional definitions from the REPL (e.g., let bound names, and @it@).-focusedEnv :: ModuleEnv -> ModContext-focusedEnv me =- ModContext- { mctxParams = parameters- , mctxDecls = mconcat (dynDecls : localDecls : importedDecls)- , mctxNames = namingEnv- , mctxNameDisp = R.toNameDisp namingEnv- , mctxTypeProvenace = fst provenance- , mctxValueProvenance = snd provenance- }+instance Monoid ModContext where+ mempty = ModContext { mctxParams = noIfaceParams+ , mctxDecls = mempty+ , mctxExported = mempty+ , mctxNames = mempty+ , mctxNameDisp = R.toNameDisp mempty+ } - where- (importedNames,importedDecls,importedProvs) = unzip3 (map loadImport imports)- localDecls = publicDecls `mappend` privateDecls- localNames = R.unqualifiedEnv localDecls `mappend`- R.modParamsNamingEnv parameters- dynDecls = deIfaceDecls (meDynEnv me)- dynNames = deNames (meDynEnv me) - namingEnv = dynNames `R.shadowing`- localNames `R.shadowing`- mconcat importedNames - provenance = shadowProvs- $ declsProv NameIsDynamicDecl dynDecls- : declsProv NameIsLocalPublic publicDecls- : declsProv NameIsLocalPrivate privateDecls- : paramProv parameters- : importedProvs+modContextOf :: ModName -> ModuleEnv -> Maybe ModContext+modContextOf mname me =+ do lm <- lookupModule mname me+ let localIface = lmInterface lm+ localNames = lmNamingEnv lm+ loadedDecls = map (ifPublic . lmInterface)+ $ getLoadedModules (meLoadedModules me)+ pure ModContext+ { mctxParams = ifParams localIface+ , mctxExported = ifaceDeclsNames (ifPublic localIface)+ , mctxDecls = mconcat (ifPrivate localIface : loadedDecls)+ , mctxNames = localNames+ , mctxNameDisp = R.toNameDisp localNames+ } - (imports, parameters, publicDecls, privateDecls) =- case meFocusedModule me of- Nothing -> (mempty, noIfaceParams, mempty, mempty)- Just fm ->- case lookupModule fm me of- Just lm ->- let Iface { .. } = lmInterface lm- in (T.mImports (lmModule lm), ifParams, ifPublic, ifPrivate)- Nothing -> panic "focusedEnv" ["Focused module is not loaded."]+dynModContext :: ModuleEnv -> ModContext+dynModContext me = mempty { mctxNames = dynNames+ , mctxNameDisp = R.toNameDisp dynNames+ , mctxDecls = deIfaceDecls (meDynEnv me)+ }+ where dynNames = deNames (meDynEnv me) - loadImport imp =- case lookupModule (iModule imp) me of- Just lm ->- let decls = ifPublic (lmInterface lm)- in ( R.interpImport imp decls- , decls- , declsProv (NameIsImportedFrom (iModule imp)) decls- )- Nothing -> panic "focusedEnv"- [ "Missing imported module: " ++ show (pp (iModule imp)) ] - -- earlier ones shadow- shadowProvs ps = let (tss,vss) = unzip ps- in (Map.unions tss, Map.unions vss) - paramProv IfaceParams { .. } = (doMap ifParamTypes, doMap ifParamFuns)- where doMap mp = const NameIsParameter <$> mp-- declsProv prov IfaceDecls { .. } =- ( Map.unions [ doMap ifTySyns, doMap ifNewtypes, doMap ifAbstractTypes ]- , doMap ifDecls- )- where doMap mp = const prov <$> mp-+-- | Given the state of the environment, compute information about what's+-- in scope on the REPL. This includes what's in the focused module, plus any+-- additional definitions from the REPL (e.g., let bound names, and @it@).+focusedEnv :: ModuleEnv -> ModContext+focusedEnv me =+ case meFocusedModule me of+ Nothing -> dynModContext me+ Just fm -> case modContextOf fm me of+ Just c -> dynModContext me <> c+ Nothing -> panic "focusedEnv"+ [ "Focused modules not loaded: " ++ show (pp fm) ]+ -- Loaded Modules -------------------------------------------------------------- @@ -350,9 +332,11 @@ -- For files we just use the cononical path, for in memory things we -- use their label. + , lmNamingEnv :: !R.NamingEnv+ -- ^ What's in scope in this module+ , lmInterface :: Iface- -- ^ The module's interface. This is for convenient. At the moment- -- we have the whole module in 'lmModule', so this could be computer.+ -- ^ The module's interface. , lmModule :: T.Module -- ^ The actual type-checked module@@ -378,8 +362,9 @@ -- | Add a freshly loaded module. If it was previously loaded, then -- the new version is ignored. addLoadedModule ::- ModulePath -> String -> Fingerprint -> T.Module -> LoadedModules -> LoadedModules-addLoadedModule path ident fp tm lm+ ModulePath -> String -> Fingerprint -> R.NamingEnv -> T.Module ->+ LoadedModules -> LoadedModules+addLoadedModule path ident fp nameEnv tm lm | isLoaded (T.mName tm) lm = lm | T.isParametrizedModule tm = lm { lmLoadedParamModules = loaded : lmLoadedParamModules lm }@@ -390,7 +375,8 @@ { lmName = T.mName tm , lmFilePath = path , lmModuleId = ident- , lmInterface = genIface tm+ , lmNamingEnv = nameEnv+ , lmInterface = T.genIface tm , lmModule = tm , lmFingerprint = fp }@@ -414,37 +400,43 @@ data DynamicEnv = DEnv { deNames :: R.NamingEnv , deDecls :: [T.DeclGroup]+ , deTySyns :: Map Name T.TySyn , deEnv :: EvalEnv } deriving Generic instance Semigroup DynamicEnv where de1 <> de2 = DEnv- { deNames = deNames de1 <> deNames de2- , deDecls = deDecls de1 <> deDecls de2- , deEnv = deEnv de1 <> deEnv de2+ { deNames = deNames de1 <> deNames de2+ , deDecls = deDecls de1 <> deDecls de2+ , deTySyns = deTySyns de1 <> deTySyns de2+ , deEnv = deEnv de1 <> deEnv de2 } instance Monoid DynamicEnv where mempty = DEnv- { deNames = mempty- , deDecls = mempty- , deEnv = mempty+ { deNames = mempty+ , deDecls = mempty+ , deTySyns = mempty+ , deEnv = mempty } mappend de1 de2 = de1 <> de2 -- | Build 'IfaceDecls' that correspond to all of the bindings in the -- dynamic environment. ----- XXX: if we ever add type synonyms or newtypes at the REPL, revisit+-- XXX: if we add newtypes, etc. at the REPL, revisit -- this. deIfaceDecls :: DynamicEnv -> IfaceDecls-deIfaceDecls DEnv { deDecls = dgs } =- mconcat [ IfaceDecls- { ifTySyns = Map.empty- , ifNewtypes = Map.empty- , ifAbstractTypes = Map.empty- , ifDecls = Map.singleton (ifDeclName ifd) ifd- }- | decl <- concatMap T.groupDecls dgs- , let ifd = mkIfaceDecl decl- ]+deIfaceDecls DEnv { deDecls = dgs, deTySyns = tySyns } =+ IfaceDecls { ifTySyns = tySyns+ , ifNewtypes = Map.empty+ , ifAbstractTypes = Map.empty+ , ifDecls = decls+ , ifModules = Map.empty+ }+ where+ decls = mconcat+ [ Map.singleton (ifDeclName ifd) ifd+ | decl <- concatMap T.groupDecls dgs+ , let ifd = T.mkIfaceDecl decl+ ]
src/Cryptol/ModuleSystem/Exports.hs view
@@ -3,63 +3,80 @@ import Data.Set(Set) import qualified Data.Set as Set+import Data.Map(Map)+import qualified Data.Map as Map import Data.Foldable(fold) import Control.DeepSeq(NFData) import GHC.Generics (Generic) import Cryptol.Parser.AST-import Cryptol.Parser.Names+import Cryptol.Parser.Names(namesD,tnamesD,tnamesNT)+import Cryptol.ModuleSystem.Name -modExports :: Ord name => Module name -> ExportSpec name+modExports :: Ord name => ModuleG mname name -> ExportSpec name modExports m = fold (concat [ exportedNames d | d <- mDecls m ])- where- names by td = [ td { tlValue = thing n } | n <- fst (by (tlValue td)) ] - 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 (DParameterFun {}) = []- exportedNames (DParameterType {}) = []- exportedNames (DParameterConstraint {}) = [] +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) }] +names :: (a -> ([Located a'], b)) -> TopLevel a -> [TopLevel a']+names by td = [ td { tlValue = thing n } | n <- fst (by (tlValue td)) ] -data ExportSpec name = ExportSpec { eTypes :: Set name- , eBinds :: Set name- } deriving (Show, Generic) +newtype ExportSpec name = ExportSpec (Map Namespace (Set name))+ deriving (Show, Generic)+ instance NFData name => NFData (ExportSpec name) instance Ord name => Semigroup (ExportSpec name) where- l <> r = ExportSpec { eTypes = eTypes l <> eTypes r- , eBinds = eBinds l <> eBinds r- }+ ExportSpec l <> ExportSpec r = ExportSpec (Map.unionWith Set.union l r) instance Ord name => Monoid (ExportSpec name) where- mempty = ExportSpec { eTypes = mempty, eBinds = mempty }- mappend = (<>)+ mempty = ExportSpec Map.empty +exportName :: Ord name => Namespace -> TopLevel name -> ExportSpec name+exportName ns n+ | tlExport n == Public = ExportSpec+ $ Map.singleton ns+ $ Set.singleton (tlValue n)+ | otherwise = mempty++exported :: Namespace -> ExportSpec name -> Set name+exported ns (ExportSpec mp) = Map.findWithDefault Set.empty ns mp+ -- | Add a binding name to the export list, if it should be exported. exportBind :: Ord name => TopLevel name -> ExportSpec name-exportBind n- | tlExport n == Public = mempty { eBinds = Set.singleton (tlValue n) }- | otherwise = mempty+exportBind = exportName NSValue -- | Add a type synonym name to the export list, if it should be exported. exportType :: Ord name => TopLevel name -> ExportSpec name-exportType n- | tlExport n == Public = mempty { eTypes = Set.singleton (tlValue n) }- | otherwise = mempty+exportType = exportName NSType +++isExported :: Ord name => Namespace -> name -> ExportSpec name -> Bool+isExported ns x (ExportSpec s) =+ case Map.lookup ns s of+ Nothing -> False+ Just mp -> Set.member x mp+ -- | Check to see if a binding is exported. isExportedBind :: Ord name => name -> ExportSpec name -> Bool-isExportedBind n = Set.member n . eBinds+isExportedBind = isExported NSValue -- | Check to see if a type synonym is exported. isExportedType :: Ord name => name -> ExportSpec name -> Bool-isExportedType n = Set.member n . eTypes---+isExportedType = isExported NSType
src/Cryptol/ModuleSystem/InstantiateModule.hs view
@@ -1,4 +1,5 @@ {-# Language FlexibleInstances, PatternGuards #-}+{-# Language BlockArguments #-} -- | Assumes that local names do not shadow top level names. module Cryptol.ModuleSystem.InstantiateModule ( instantiateModule@@ -10,12 +11,13 @@ 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)-import Cryptol.Utils.Ident(ModName,modParamIdent) {- XXX: Should we simplify constraints in the instantiated modules?@@ -33,15 +35,23 @@ ModName {- ^ Name of the new module -} -> Map TParam Type {- ^ Type params -} -> Map Name Expr {- ^ Value parameters -} ->- m ([Located Prop], Module)- -- ^ Instantiated constraints, fresh module, new supply-instantiateModule func newName tpMap vpMap =- runReaderT newName $+ 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@@ -60,7 +70,8 @@ let renamedDecls = inst env (mDecls func) paramDecls = map (mkParamDecl su vpNames) (Map.toList vpMap) - return ( goals+ return ( ren+ , goals , Module { mName = newName , mExports = renamedExports@@ -72,6 +83,9 @@ , mParamConstraints = [] , mParamFuns = Map.empty , mDecls = paramDecls ++ renamedDecls++ , mSubModules = mempty+ , mFunctors = mempty } ) where@@ -110,7 +124,7 @@ -------------------------------------------------------------------------------- -type InstM = ReaderT ModName+type InstM = ReaderT ModPath -- | Generate a new instance of a declared name. freshenName :: FreshM m => Name -> InstM m Name@@ -119,13 +133,15 @@ let sys = case nameInfo x of Declared _ s -> s _ -> UserName- liftSupply (mkDeclared m sys (nameIdent x) (nameFixity x) (nameLoc x))+ 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 m UserName newName (nameFixity x) (nameLoc x))+ liftSupply (mkDeclared (nameNamespace x)+ m UserName newName (nameFixity x) (nameLoc x)) @@ -263,11 +279,14 @@ where y = Map.findWithDefault x x (tyNameMap env) instance Inst (ExportSpec Name) where- inst env es = ExportSpec { eTypes = Set.map instT (eTypes es)- , eBinds = Set.map instV (eBinds es)- }- where instT x = Map.findWithDefault x x (tyNameMap env)- instV x = Map.findWithDefault x x (funNameMap env)+ 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
src/Cryptol/ModuleSystem/Interface.hs view
@@ -12,24 +12,27 @@ {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-} module Cryptol.ModuleSystem.Interface (- Iface(..)+ Iface+ , IfaceG(..) , IfaceDecls(..) , IfaceTySyn, ifTySynName , IfaceNewtype- , IfaceDecl(..), mkIfaceDecl+ , IfaceDecl(..) , IfaceParams(..) - , genIface+ , emptyIface , ifacePrimMap , noIfaceParams+ , isEmptyIfaceParams+ , ifaceIsFunctor+ , flatPublicIface+ , flatPublicDecls+ , filterIfaceDecls+ , ifaceDeclsNames ) where -import Cryptol.ModuleSystem.Name-import Cryptol.TypeCheck.AST-import Cryptol.Utils.Ident (ModName)-import Cryptol.Utils.Panic(panic)-import Cryptol.Parser.Position(Located)-+import Data.Set(Set)+import qualified Data.Set as Set import qualified Data.Map as Map import Data.Semigroup import Data.Text (Text)@@ -40,15 +43,52 @@ import Prelude () import Prelude.Compat +import Cryptol.ModuleSystem.Name+import Cryptol.Utils.Ident (ModName)+import Cryptol.Utils.Panic(panic)+import Cryptol.Utils.Fixity(Fixity)+import Cryptol.Parser.AST(Pragma)+import Cryptol.Parser.Position(Located)+import Cryptol.TypeCheck.Type + -- | The resulting interface generated by a module that has been typechecked.-data Iface = Iface- { ifModName :: !ModName -- ^ Module name+data IfaceG mname = Iface+ { ifModName :: !mname -- ^ Module name , ifPublic :: IfaceDecls -- ^ Exported definitions , ifPrivate :: IfaceDecls -- ^ Private defintiions , ifParams :: IfaceParams -- ^ Uninterpreted constants (aka module params) } 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)+ )++ where+ (fun,nofun) = Map.partition ifaceIsFunctor (ifModules ifs)+++type Iface = IfaceG ModName++emptyIface :: mname -> IfaceG mname+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@@ -62,29 +102,57 @@ , ifParamFuns = Map.empty } +isEmptyIfaceParams :: IfaceParams -> Bool+isEmptyIfaceParams IfaceParams { .. } =+ Map.null ifParamTypes && null ifParamConstraints && Map.null ifParamFuns+ data IfaceDecls = IfaceDecls { ifTySyns :: Map.Map Name IfaceTySyn , ifNewtypes :: Map.Map Name IfaceNewtype , ifAbstractTypes :: Map.Map Name IfaceAbstractType , ifDecls :: Map.Map Name IfaceDecl+ , ifModules :: !(Map.Map Name (IfaceG Name)) } deriving (Show, Generic, NFData) +filterIfaceDecls :: (Name -> Bool) -> IfaceDecls -> IfaceDecls+filterIfaceDecls p ifs = IfaceDecls+ { ifTySyns = filterMap (ifTySyns ifs)+ , ifNewtypes = filterMap (ifNewtypes ifs)+ , ifAbstractTypes = filterMap (ifAbstractTypes ifs)+ , ifDecls = filterMap (ifDecls ifs)+ , ifModules = filterMap (ifModules ifs)+ }+ where+ filterMap :: Map.Map Name a -> Map.Map Name a+ filterMap = Map.filterWithKey (\k _ -> p k)++ifaceDeclsNames :: IfaceDecls -> Set Name+ifaceDeclsNames i = Set.unions [ Map.keysSet (ifTySyns i)+ , Map.keysSet (ifNewtypes i)+ , Map.keysSet (ifAbstractTypes i)+ , Map.keysSet (ifDecls i)+ , Map.keysSet (ifModules i)+ ]++ instance Semigroup IfaceDecls where l <> r = IfaceDecls { ifTySyns = Map.union (ifTySyns l) (ifTySyns r) , ifNewtypes = Map.union (ifNewtypes l) (ifNewtypes r) , ifAbstractTypes = Map.union (ifAbstractTypes l) (ifAbstractTypes r) , ifDecls = Map.union (ifDecls l) (ifDecls r)+ , ifModules = Map.union (ifModules l) (ifModules r) } instance Monoid IfaceDecls where- mempty = IfaceDecls Map.empty Map.empty Map.empty Map.empty+ mempty = IfaceDecls Map.empty Map.empty Map.empty Map.empty Map.empty mappend l r = l <> r 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) } type IfaceTySyn = TySyn@@ -103,61 +171,6 @@ , ifDeclFixity :: Maybe Fixity -- ^ Fixity information , ifDeclDoc :: Maybe Text -- ^ Documentation } deriving (Show, Generic, NFData)--mkIfaceDecl :: Decl -> IfaceDecl-mkIfaceDecl d = IfaceDecl- { ifDeclName = dName d- , ifDeclSig = dSignature d- , ifDeclPragmas = dPragmas d- , ifDeclInfix = dInfix d- , ifDeclFixity = dFixity d- , ifDeclDoc = dDoc d- }---- | Generate an Iface from a typechecked module.-genIface :: Module -> Iface-genIface m = Iface- { ifModName = mName m-- , ifPublic = IfaceDecls- { ifTySyns = tsPub- , ifNewtypes = ntPub- , ifAbstractTypes = atPub- , ifDecls = dPub- }-- , ifPrivate = IfaceDecls- { ifTySyns = tsPriv- , ifNewtypes = ntPriv- , ifAbstractTypes = atPriv- , ifDecls = dPriv- }-- , ifParams = IfaceParams- { ifParamTypes = mParamTypes m- , ifParamConstraints = mParamConstraints m- , ifParamFuns = mParamFuns 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)-- (dPub,dPriv) =- Map.partitionWithKey (\ qn _ -> qn `isExportedBind` mExports m)- $ Map.fromList [ (qn,mkIfaceDecl d) | dg <- mDecls m- , d <- groupDecls dg- , let qn = dName d- ] -- | Produce a PrimMap from an interface.
src/Cryptol/ModuleSystem/Monad.hs view
@@ -21,6 +21,7 @@ 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)@@ -201,7 +202,7 @@ FailedToParameterizeModDefs x xs -> hang (text "[error] Parameterized module" <+> pp x <+> text "has polymorphic parameters:")- 4 (hsep $ punctuate comma $ map pp xs)+ 4 (commaSep (map pp xs)) NotAParameterizedModule x -> text "[error] Module" <+> pp x <+> text "does not have parameters."@@ -463,12 +464,16 @@ _ -> return (FromModule noModuleName) getIface :: P.ModName -> ModuleM Iface-getIface mn =- do env <- ModuleT get- case lookupModule mn env of- Just lm -> return (lmInterface lm)- Nothing -> panic "ModuleSystem" ["Interface not available", show (pp mn)]+getIface mn = ($ mn) <$> getIfaces +getIfaces :: ModuleM (P.ModName -> Iface)+getIfaces = doLookup <$> ModuleT get+ where+ doLookup env mn =+ case lookupModule mn env of+ Just lm -> lmInterface lm+ Nothing -> panic "ModuleSystem" ["Interface not available", show (pp mn)]+ getLoaded :: P.ModName -> ModuleM T.Module getLoaded mn = ModuleT $ do env <- get@@ -505,14 +510,16 @@ env <- get set $! env { meLoadedModules = removeLoadedModule rm (meLoadedModules env) } -loadedModule :: ModulePath -> Fingerprint -> T.Module -> ModuleM ()-loadedModule path fp m = ModuleT $ do+loadedModule ::+ ModulePath -> Fingerprint -> NamingEnv -> T.Module -> ModuleM ()+loadedModule path fp nameEnv 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 m (meLoadedModules env) }+ set $! env { meLoadedModules = addLoadedModule path ident fp nameEnv m+ (meLoadedModules env) } modifyEvalEnv :: (EvalEnv -> E.Eval EvalEnv) -> ModuleM () modifyEvalEnv f = ModuleT $ do@@ -569,16 +576,6 @@ setDynEnv denv = ModuleT $ do me <- get set $! me { meDynEnv = denv }--setSolver :: T.SolverConfig -> ModuleM ()-setSolver cfg = ModuleT $ do- me <- get- set $! me { meSolverConfig = cfg }--getSolverConfig :: ModuleM T.SolverConfig-getSolverConfig = ModuleT $ do- me <- get- return (meSolverConfig me) -- | Usefule for logging. For example: @withLogger logPutStrLn "Hello"@ withLogger :: (Logger -> a -> IO b) -> a -> ModuleM b
src/Cryptol/ModuleSystem/Name.hs view
@@ -14,6 +14,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-} -- for the instances of RunM and BaseM {-# LANGUAGE UndecidableInstances #-} @@ -26,10 +27,13 @@ , nameInfo , nameLoc , nameFixity+ , nameNamespace , asPrim- , cmpNameLexical- , cmpNameDisplay+ , asOrigName , ppLocName+ , Namespace(..)+ , ModPath(..)+ , cmpNameDisplay -- ** Creation , mkDeclared@@ -49,33 +53,35 @@ , lookupPrimType ) where -import Cryptol.Parser.Position (Range,Located(..),emptyRange)-import Cryptol.Utils.Fixity-import Cryptol.Utils.Ident-import Cryptol.Utils.Panic-import Cryptol.Utils.PP-- import Control.DeepSeq import qualified Data.Map as Map import qualified Data.Monoid as M-import Data.Ord (comparing)-import qualified Data.Text as Text-import Data.Char(isAlpha,toUpper) import GHC.Generics (Generic) import MonadLib import Prelude () import Prelude.Compat+import qualified Data.Text as Text+import Data.Char(isAlpha,toUpper) ++import Cryptol.Parser.Position (Range,Located(..),emptyRange)+import Cryptol.Utils.Fixity+import Cryptol.Utils.Ident+import Cryptol.Utils.Panic+import Cryptol.Utils.PP+++ -- Names ----------------------------------------------------------------------- -- | Information about the binding site of the name.-data NameInfo = Declared !ModName !NameSource+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@@ -84,6 +90,8 @@ , nInfo :: !NameInfo -- ^ Information about the origin of this name. + , nNamespace :: !Namespace+ , nIdent :: !Ident -- ^ The name of the identifier @@ -100,6 +108,7 @@ data NameSource = SystemName | UserName deriving (Generic, NFData, Show, Eq) + instance Eq Name where a == b = compare a b == EQ a /= b = compare a b /= EQ@@ -107,54 +116,41 @@ instance Ord Name where compare a b = compare (nUnique a) (nUnique b) --- | Compare two names lexically.-cmpNameLexical :: Name -> Name -> Ordering-cmpNameLexical l r =- case (nameInfo l, nameInfo r) of - (Declared nsl _,Declared nsr _) ->- case compare nsl nsr of- EQ -> comparing nameIdent l r- cmp -> cmp - (Parameter,Parameter) -> comparing nameIdent l r-- (Declared nsl _,Parameter) -> compare (modNameToText nsl)- (identText (nameIdent r))- (Parameter,Declared nsr _) -> compare (identText (nameIdent l))- (modNameToText nsr)-- -- | Compare two names by the way they would be displayed.+-- This is used to order names nicely when showing what's in scope cmpNameDisplay :: NameDisp -> Name -> Name -> Ordering cmpNameDisplay disp l r =- case (nameInfo l, nameInfo r) of+ case (asOrigName l, asOrigName r) of - (Declared nsl _, Declared nsr _) -> -- XXX: uses system name info?- let pfxl = fmtModName nsl (getNameFormat nsl (nameIdent l) disp)- pfxr = fmtModName nsr (getNameFormat nsr (nameIdent r) disp)- in case cmpText pfxl pfxr of- EQ -> cmpName l r- cmp -> cmp+ (Just ogl, Just ogr) -> -- XXX: uses system name info?+ case cmpText (fmtPref ogl) (fmtPref ogr) of+ EQ -> cmpName l r+ cmp -> cmp - (Parameter,Parameter) -> cmpName l r+ (Nothing,Nothing) -> cmpName l r - (Declared nsl _,Parameter) ->- let pfxl = fmtModName nsl (getNameFormat nsl (nameIdent l) disp)- in case cmpText pfxl (identText (nameIdent r)) of- EQ -> GT- cmp -> cmp+ (Just ogl,Nothing) ->+ case cmpText (fmtPref ogl) (identText (nameIdent r)) of+ EQ -> GT+ cmp -> cmp - (Parameter,Declared nsr _) ->- let pfxr = fmtModName nsr (getNameFormat nsr (nameIdent r) disp)- in case cmpText (identText (nameIdent l)) pfxr of- EQ -> LT- cmp -> cmp+ (Nothing,Just ogr) ->+ case cmpText (identText (nameIdent l)) (fmtPref ogr) of+ EQ -> LT+ cmp -> cmp where cmpName xs ys = cmpIdent (nameIdent xs) (nameIdent ys) cmpIdent xs ys = cmpText (identText xs) (identText ys) + --- let pfxl = fmtModName nsl (getNameFormat nsl (nameIdent l) disp)+ fmtPref og = case getNameFormat og disp of+ UnQualified -> ""+ Qualified q -> modNameToText q+ NotInScope -> Text.pack $ show $ pp (ogModule og)+ -- Note that this assumes that `xs` is `l` and `ys` is `r` cmpText xs ys = case (Text.null xs, Text.null ys) of@@ -169,23 +165,18 @@ | a == '_' = 1 | otherwise = 0 ++ -- | Figure out how the name should be displayed, by referencing the display -- function in the environment. NOTE: this function doesn't take into account -- the need for parentheses. ppName :: Name -> Doc-ppName Name { .. } =- case nInfo of+ppName nm =+ case asOrigName nm of+ Just og -> pp og+ Nothing -> pp (nameIdent nm) - Declared m _ -> withNameDisp $ \disp ->- case getNameFormat m nIdent disp of- Qualified m' -> ppQual m' <.> pp nIdent- UnQualified -> pp nIdent- NotInScope -> ppQual m <.> pp nIdent -- XXX: only when not in scope?- where- ppQual mo = if mo == exprModName then empty else pp mo <.> text "::" - Parameter -> pp nIdent- instance PP Name where ppPrec _ = ppPrefixName @@ -199,6 +190,7 @@ ppPrefixName n @ Name { .. } = optParens (isInfixIdent nIdent) (ppName n) + -- | Pretty-print a name with its source location information. ppLocName :: Name -> Doc ppLocName n = pp Located { srcRange = nameLoc n, thing = n }@@ -209,6 +201,9 @@ nameIdent :: Name -> Ident nameIdent = nIdent +nameNamespace :: Name -> Namespace+nameNamespace = nNamespace+ nameInfo :: Name -> NameInfo nameInfo = nInfo @@ -218,23 +213,33 @@ nameFixity :: Name -> Maybe Fixity nameFixity = nFixity -+-- | Primtiives must be in a top level module, at least for now. asPrim :: Name -> Maybe PrimIdent asPrim Name { .. } = case nInfo of- Declared p _ -> Just $ PrimIdent p $ identText nIdent- _ -> Nothing+ Declared (TopModule m) _ -> Just $ PrimIdent m $ identText nIdent+ _ -> Nothing toParamInstName :: Name -> Name toParamInstName n = case nInfo n of- Declared m s -> n { nInfo = Declared (paramInstModName m) s }+ Declared m s -> n { nInfo = Declared (apPathRoot paramInstModName m) s } Parameter -> n asParamName :: Name -> Name asParamName n = n { nInfo = Parameter } +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 + -- Name Supply ----------------------------------------------------------------- class Monad m => FreshM m where@@ -321,15 +326,17 @@ -- Name Construction ----------------------------------------------------------- -- | Make a new name for a declaration.-mkDeclared :: ModName -> NameSource -> Ident -> Maybe Fixity -> Range -> Supply -> (Name,Supply)-mkDeclared m sys nIdent nFixity nLoc s =+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') -- | Make a new parameter name.-mkParameter :: Ident -> Range -> Supply -> (Name,Supply)-mkParameter nIdent nLoc s =+mkParameter :: Namespace -> Ident -> Range -> Supply -> (Name,Supply)+mkParameter nNamespace nIdent nLoc s = let (nUnique,s') = nextUnique s nFixity = Nothing in (Name { nInfo = Parameter, .. }, s')@@ -340,6 +347,7 @@ , nIdent = packIdent "$modParams" , nLoc = emptyRange , nUnique = 0x01+ , nNamespace = NSValue } -- Prim Maps -------------------------------------------------------------------
src/Cryptol/ModuleSystem/NamingEnv.hs view
@@ -15,23 +15,18 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE OverloadedStrings #-} module Cryptol.ModuleSystem.NamingEnv where -import Cryptol.ModuleSystem.Interface-import Cryptol.ModuleSystem.Name-import Cryptol.Parser.AST-import Cryptol.Parser.Name(isGeneratedName)-import Cryptol.Parser.Position-import qualified Cryptol.TypeCheck.AST as T-import Cryptol.Utils.PP-import Cryptol.Utils.Panic (panic)- import Data.List (nub)-import Data.Maybe (fromMaybe)+import Data.Maybe (fromMaybe,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)+import MonadLib (runId,Id,StateT,runStateT,lift,sets_,forM_) import GHC.Generics (Generic) import Control.DeepSeq@@ -39,46 +34,71 @@ import Prelude () import Prelude.Compat +import Cryptol.Utils.PP+import Cryptol.Utils.Panic (panic)+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 + -- Naming Environment ---------------------------------------------------------- -- | The 'NamingEnv' is used by the renamer to determine what -- identifiers refer to.-data NamingEnv = NamingEnv { neExprs :: !(Map.Map PName [Name])- -- ^ Expr renaming environment- , neTypes :: !(Map.Map PName [Name])- -- ^ Type renaming environment- } deriving (Show, Generic, NFData)+newtype NamingEnv = NamingEnv (Map Namespace (Map PName [Name]))+ 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+++-- | Get the names in a given namespace+namespaceMap :: Namespace -> NamingEnv -> Map PName [Name]+namespaceMap ns (NamingEnv env) = Map.findWithDefault Map.empty ns env++-- | 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 qn ro = Map.findWithDefault [] qn (neExprs ro)+lookupValNames = lookupNS NSValue -- | Return a list of type-level names to which this parsed name may refer. lookupTypeNames :: PName -> NamingEnv -> [Name]-lookupTypeNames qn ro = Map.findWithDefault [] qn (neTypes ro)+lookupTypeNames = lookupNS NSType +-- | Singleton renaming environment for the given namespace.+singletonNS :: Namespace -> PName -> Name -> NamingEnv+singletonNS ns pn n = NamingEnv (Map.singleton ns (Map.singleton pn [n])) +-- | Singleton expression renaming environment.+singletonE :: PName -> Name -> NamingEnv+singletonE = singletonNS NSValue -instance Semigroup NamingEnv where- l <> r =- NamingEnv { neExprs = Map.unionWith merge (neExprs l) (neExprs r)- , neTypes = Map.unionWith merge (neTypes l) (neTypes r) }+-- | Singleton type renaming environment.+singletonT :: PName -> Name -> NamingEnv+singletonT = singletonNS NSType -instance Monoid NamingEnv where- mempty =- NamingEnv { neExprs = Map.empty- , neTypes = Map.empty } - mappend l r = l <> r+namingEnvRename :: (Name -> Name) -> NamingEnv -> NamingEnv+namingEnvRename f (NamingEnv mp) = NamingEnv (ren <$> mp)+ where+ ren nsm = map f <$> nsm - mconcat envs =- NamingEnv { neExprs = Map.unionsWith merge (map neExprs envs)- , neTypes = Map.unionsWith merge (map neTypes envs) } +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 #-}- {-# INLINE mappend #-}- {-# INLINE mconcat #-} -- | Merge two name maps, collapsing cases where the entries are the same, and@@ -87,62 +107,61 @@ merge xs ys | xs == ys = xs | otherwise = nub (xs ++ ys) +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)+ -- | Generate a mapping from 'PrimIdent' to 'Name' for a -- given naming environment. toPrimMap :: NamingEnv -> PrimMap-toPrimMap NamingEnv { .. } = PrimMap { .. }+toPrimMap env =+ PrimMap+ { primDecls = fromNS NSValue+ , primTypes = fromNS NSType+ } where+ fromNS ns = Map.fromList+ [ entry x | xs <- Map.elems (namespaceMap ns env), x <- xs ]+ entry n = case asPrim n of Just p -> (p,n) Nothing -> panic "toPrimMap" [ "Not a declared name?" , show n ] - primDecls = Map.fromList [ entry n | ns <- Map.elems neExprs, n <- ns ]- primTypes = Map.fromList [ entry n | ns <- Map.elems neTypes, n <- ns ] -- | Generate a display format based on a naming environment. toNameDisp :: NamingEnv -> NameDisp-toNameDisp NamingEnv { .. } = NameDisp display+toNameDisp env = NameDisp (`Map.lookup` names) where- display mn ident = Map.lookup (mn,ident) names-- -- only format declared names, as parameters don't need any special- -- formatting. names = Map.fromList- $ [ mkEntry (mn, nameIdent n) pn | (pn,ns) <- Map.toList neExprs- , n <- ns- , Declared mn _ <- [nameInfo n] ]-- ++ [ mkEntry (mn, nameIdent n) pn | (pn,ns) <- Map.toList neTypes- , n <- ns- , Declared mn _ <- [nameInfo n] ]-- mkEntry key pn = (key,fmt)- where fmt = case getModName pn of- Just ns -> Qualified ns- Nothing -> UnQualified+ [ (og, qn)+ | ns <- [ NSValue, NSType, NSModule ]+ , (pn,xs) <- Map.toList (namespaceMap ns env)+ , x <- xs+ , og <- maybeToList (asOrigName x)+ , let qn = case getModName pn of+ Just q -> Qualified q+ Nothing -> UnQualified+ ] -- | Produce sets of visible names for types and declarations. ----- NOTE: if entries in the NamingEnv would have produced a name clash, they will--- be omitted from the resulting sets.-visibleNames :: NamingEnv -> ({- types -} Set.Set Name- ,{- decls -} Set.Set Name)--visibleNames NamingEnv { .. } = (types,decls)+-- 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- types = Set.fromList [ n | [n] <- Map.elems neTypes ]- decls = Set.fromList [ n | [n] <- Map.elems neExprs ]+ check names =+ case names of+ [name] -> Just name+ _ -> Nothing -- | Qualify all symbols in a 'NamingEnv' with the given prefix. qualify :: ModName -> NamingEnv -> NamingEnv-qualify pfx NamingEnv { .. } =- NamingEnv { neExprs = Map.mapKeys toQual neExprs- , neTypes = Map.mapKeys toQual neTypes- }-+qualify pfx (NamingEnv env) = NamingEnv (Map.mapKeys toQual <$> env) where -- XXX we don't currently qualify fresh names toQual (Qual _ n) = Qual pfx n@@ -150,53 +169,87 @@ toQual n@NewName{} = n filterNames :: (PName -> Bool) -> NamingEnv -> NamingEnv-filterNames p NamingEnv { .. } =- NamingEnv { neExprs = Map.filterWithKey check neExprs- , neTypes = Map.filterWithKey check neTypes- }- where- check :: PName -> a -> Bool- check n _ = p n+filterNames p (NamingEnv env) = NamingEnv (Map.filterWithKey check <$> env)+ where check n _ = p n --- | Singleton type renaming environment.-singletonT :: PName -> Name -> NamingEnv-singletonT qn tn = mempty { neTypes = Map.singleton qn [tn] }---- | Singleton expression renaming environment.-singletonE :: PName -> Name -> NamingEnv-singletonE qn en = mempty { neExprs = Map.singleton qn [en] }- -- | Like mappend, but when merging, prefer values on the lhs. shadowing :: NamingEnv -> NamingEnv -> NamingEnv-shadowing l r = NamingEnv- { neExprs = Map.union (neExprs l) (neExprs r)- , neTypes = Map.union (neTypes l) (neTypes r) }+shadowing (NamingEnv l) (NamingEnv r) = NamingEnv (Map.unionWith Map.union l r) travNamingEnv :: Applicative f => (Name -> f Name) -> NamingEnv -> f NamingEnv-travNamingEnv f ne = NamingEnv <$> neExprs' <*> neTypes'- where- neExprs' = traverse (traverse f) (neExprs ne)- neTypes' = traverse (traverse f) (neTypes ne)+travNamingEnv f (NamingEnv mp) =+ NamingEnv <$> traverse (traverse (traverse f)) mp -data InModule a = InModule !ModName a+{- | 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) --- | Generate a 'NamingEnv' using an explicit supply.-namingEnv' :: BindsNames a => a -> Supply -> (NamingEnv,Supply)-namingEnv' a supply = runId (runSupplyT supply (runBuild (namingEnv a)))--newTop :: FreshM m => ModName -> PName -> Maybe Fixity -> Range -> m Name-newTop ns thing fx rng = liftSupply (mkDeclared ns src (getIdent thing) fx rng)+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 => PName -> Range -> m Name-newLocal thing rng = liftSupply (mkParameter (getIdent thing) rng)+newLocal :: FreshM m => Namespace -> PName -> Range -> m Name+newLocal ns thing rng = liftSupply (mkParameter ns (getIdent thing) rng) newtype BuildNamingEnv = BuildNamingEnv { runBuild :: SupplyT Id NamingEnv } ++buildNamingEnv :: BuildNamingEnv -> Supply -> (NamingEnv,Supply)+buildNamingEnv b supply = runId $ runSupplyT supply $ runBuild b++-- | Generate a 'NamingEnv' using an explicit supply.+defsOf :: BindsNames a => a -> Supply -> (NamingEnv,Supply)+defsOf = buildNamingEnv . namingEnv+++--------------------------------------------------------------------------------+-- 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)+ 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)++--------------------------------------------------------------------------------++++ instance Semigroup BuildNamingEnv where BuildNamingEnv a <> BuildNamingEnv b = BuildNamingEnv $ do x <- a@@ -212,6 +265,10 @@ do ns <- sequence (map runBuild bs) return (mconcat ns) +--------------------------------------------------------------------------------+++ -- | Things that define exported names. class BindsNames a where namingEnv :: a -> BuildNamingEnv@@ -235,12 +292,12 @@ {-# INLINE namingEnv #-} --- | Interpret an import in the context of an interface, to produce a name--- environment for the renamer, and a 'NameDisp' for pretty-printing.-interpImport :: Import {- ^ The import declarations -} ->- IfaceDecls {- ^ Declarations of imported module -} ->++-- | Adapt the things exported by something to the specific import/open.+interpImportEnv :: ImportG name {- ^ The import declarations -} ->+ NamingEnv {- ^ All public things coming in -} -> NamingEnv-interpImport imp publicDecls = qualified+interpImportEnv imp public = qualified where -- optionally qualify names based on the import@@ -257,16 +314,21 @@ | otherwise = public - -- generate the initial environment from the public interface, where no names- -- are qualified- public = unqualifiedEnv publicDecls +-- | 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 ]+ mconcat [ exprs, tySyns, ntTypes, absTys, ntExprs, mods ] where toPName n = mkUnqual (nameIdent n) @@ -275,16 +337,17 @@ 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 { neExprs = Map.fromList $ map fromFu $ Map.keys ifParamFuns- , neTypes = Map.fromList $ map fromTy $ Map.elems ifParamTypes- }-+ 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) @@ -301,14 +364,16 @@ -- mapping only from unqualified names to qualified ones. instance BindsNames ImportIface where namingEnv (ImportIface imp Iface { .. }) = BuildNamingEnv $- return (interpImport imp ifPublic)+ return (interpImportIface imp ifPublic) {-# INLINE namingEnv #-} -- | Introduce the name instance BindsNames (InModule (Bind PName)) where- namingEnv (InModule ns b) = BuildNamingEnv $+ namingEnv (InModule mb b) = BuildNamingEnv $ do let Located { .. } = bName b- n <- newTop ns thing (bFixity b) srcRange+ n <- case mb of+ Just m -> newTop NSValue m thing (bFixity b) srcRange+ Nothing -> newLocal NSValue thing srcRange -- local fixitiies? return (singletonE thing n) @@ -316,16 +381,19 @@ instance BindsNames (TParam PName) where namingEnv TParam { .. } = BuildNamingEnv $ do let range = fromMaybe emptyRange tpRange- n <- newLocal tpName range+ 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 Module { .. } = foldMap (namingEnv . InModule ns) mDecls- where- ns = thing mName+ 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@@ -335,60 +403,70 @@ DParameterType d -> namingEnv (InModule ns d) DParameterConstraint {} -> mempty DParameterFun d -> namingEnv (InModule ns d)- Include _ -> mempty+ 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 ns PrimType { .. }) =+ namingEnv (InModule ~(Just m) PrimType { .. }) = BuildNamingEnv $ do let Located { .. } = primTName- nm <- newTop ns thing primTFixity srcRange+ nm <- newTop NSType m thing primTFixity srcRange pure (singletonT thing nm) instance BindsNames (InModule (ParameterFun PName)) where- namingEnv (InModule ns ParameterFun { .. }) = BuildNamingEnv $+ namingEnv (InModule ~(Just ns) ParameterFun { .. }) = BuildNamingEnv $ do let Located { .. } = pfName- ntName <- newTop ns thing pfFixity srcRange+ ntName <- newTop NSValue ns thing pfFixity srcRange return (singletonE thing ntName) instance BindsNames (InModule (ParameterType PName)) where- namingEnv (InModule ns ParameterType { .. }) = BuildNamingEnv $+ 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 ns thing Nothing srcRange+ 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 ns Newtype { .. }) = BuildNamingEnv $+ namingEnv (InModule ~(Just ns) Newtype { .. }) = BuildNamingEnv $ do let Located { .. } = nName- ntName <- newTop ns thing Nothing srcRange+ 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 -> BuildNamingEnv $- do n <- mkName (bName b) (bFixity b)- return (singletonE (thing (bName b)) n)-+ 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')- DPatBind _pat _e -> panic "ModuleSystem" ["Unexpected pattern binding"]- DFixity{} -> panic "ModuleSystem" ["Unexpected fixity declaration"]+ DRec {} -> panic "namingEnv" [ "DRec" ]+ DPatBind _pat _e -> panic "namingEnv" ["Unexpected pattern binding"]+ DFixity{} -> panic "namingEnv" ["Unexpected fixity declaration"] where - mkName ln fx = newTop pfx (thing ln) fx (srcRange ln)+ 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 ln Nothing+ do n <- mkName NSValue ln Nothing return (singletonE (thing ln) n) qualType ln f = BuildNamingEnv $- do n <- mkName ln f+ do n <- mkName NSType ln f return (singletonT (thing ln) n)
src/Cryptol/ModuleSystem/Renamer.hs view
@@ -6,19 +6,13 @@ -- Stability : provisional -- Portability : portable -{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE OverloadedStrings #-}+{-# Language RecordWildCards #-}+{-# Language FlexibleInstances #-}+{-# Language FlexibleContexts #-}+{-# Language BlockArguments #-} module Cryptol.ModuleSystem.Renamer ( NamingEnv(), shadowing- , BindsNames(..), InModule(..), namingEnv'- , checkNamingEnv+ , BindsNames(..), InModule(..) , shadowNames , Rename(..), runRenamer, RenameM() , RenamerError(..)@@ -26,429 +20,449 @@ , renameVar , renameType , renameModule+ , renameTopDecls+ , RenamerInfo(..)+ , NameType(..)+ , RenamedModule(..) ) where +import Prelude ()+import Prelude.Compat++import Data.Either(partitionEithers)+import Data.Maybe(fromJust)+import Data.List(find,foldl')+import Data.Foldable(toList)+import Data.Map.Strict(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 Cryptol.ModuleSystem.Name import Cryptol.ModuleSystem.NamingEnv import Cryptol.ModuleSystem.Exports+import Cryptol.Parser.Position(getLoc) import Cryptol.Parser.AST-import Cryptol.Parser.Position-import Cryptol.Parser.Selector(ppNestedSels,selName)+import Cryptol.Parser.Selector(selName) import Cryptol.Utils.Panic (panic)-import Cryptol.Utils.PP import Cryptol.Utils.RecordMap+import Cryptol.Utils.Ident(allNamespaces,packModName) -import Data.List(find)-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 Data.Set (Set)-import qualified Data.Set as Set-import MonadLib hiding (mapM, mapM_)+import Cryptol.ModuleSystem.Interface+import Cryptol.ModuleSystem.Renamer.Error+import Cryptol.ModuleSystem.Renamer.Monad -import GHC.Generics (Generic)-import Control.DeepSeq -import Prelude ()-import Prelude.Compat+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+ } --- Errors ----------------------------------------------------------------------+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+ pure RenamedModule+ { rmModule = m1+ , rmDefines = env+ , rmInScope = inScope+ , rmImported = ifs+ -- XXX: maybe we should keep the nested defines too?+ } -data RenamerError- = MultipleSyms (Located PName) [Name] NameDisp- -- ^ Multiple imported symbols contain this name+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) - | UnboundExpr (Located PName) NameDisp- -- ^ Expression name is not bound to any definition+ 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) - | UnboundType (Located PName) NameDisp- -- ^ Type name is not bound to any definition+ pure (env,ds1) - | OverlappingSyms [Name] NameDisp- -- ^ An environment has produced multiple overlapping symbols+-- | 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 -> []+ ) - | ExpectedValue (Located PName) NameDisp- -- ^ When a value is expected from the naming environment, but one or more- -- types exist instead. - | ExpectedType (Located PName) NameDisp- -- ^ When a type is missing from the naming environment, but one or more- -- values exist with the same name.+ classify d (ms,ds) =+ case d of+ DModule tl -> (tl : ms, ds)+ _ -> (ms, d : ds) - | FixityError (Located Name) Fixity (Located Name) Fixity NameDisp- -- ^ When the fixity of two operators conflict - | InvalidConstraint (Type PName) NameDisp- -- ^ When it's not possible to produce a Prop from a Type.+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" ] - | MalformedBuiltin (Type PName) PName NameDisp- -- ^ When a builtin type/type-function is used incorrectly. - | BoundReservedType PName (Maybe Range) Doc NameDisp- -- ^ When a builtin type is named in a binder.+class Rename f where+ rename :: f PName -> RenameM (f Name) - | OverlappingRecordUpdate (Located [Selector]) (Located [Selector]) NameDisp- -- ^ When record updates overlap (e.g., @{ r | x = e1, x.y = e2 }@)- deriving (Show, Generic, NFData) -instance PP RenamerError where- ppPrec _ e = case e of+-- | Returns:+--+-- * Interfaces for imported things,+-- * Things defines in the module+-- * Renamed module+renameModule' ::+ NestedMods -> NamingEnv -> ModPath -> 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 - MultipleSyms lqn qns disp -> fixNameDisp disp $- hang (text "[error] at" <+> pp (srcRange lqn))- 4 $ (text "Multiple definitions for symbol:" <+> pp (thing lqn))- $$ vcat (map ppLocName qns)+ (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) - UnboundExpr lqn disp -> fixNameDisp disp $- hang (text "[error] at" <+> pp (srcRange lqn))- 4 (text "Value not in scope:" <+> pp (thing lqn)) - UnboundType lqn disp -> fixNameDisp disp $- hang (text "[error] at" <+> pp (srcRange lqn))- 4 (text "Type not in scope:" <+> pp (thing lqn))+renameDecls :: [Decl PName] -> RenameM [Decl Name]+renameDecls ds =+ do (ds1,deps) <- depGroup (traverse rename ds)+ let toNode d = let x = NamedThing (declName d)+ 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 ->+ let (rds,xs) = unzip ds_xs+ in case mapM validRecursiveD rds of+ Nothing -> do record (InvalidDependency xs)+ pure rds+ Just bs ->+ do checkSameModule xs+ pure [DRec bs]+ concat <$> mapM fromSCC ordered - OverlappingSyms qns disp -> fixNameDisp disp $- hang (text "[error]")- 4 $ text "Overlapping symbols defined:"- $$ vcat (map ppLocName qns) - ExpectedValue lqn disp -> fixNameDisp disp $- hang (text "[error] at" <+> pp (srcRange lqn))- 4 (fsep [ text "Expected a value named", quotes (pp (thing lqn))- , text "but found a type instead"- , text "Did you mean `(" <.> pp (thing lqn) <.> text")?" ])+validRecursiveD :: Decl name -> Maybe (Bind name)+validRecursiveD d =+ case d of+ DBind b -> Just b+ DLocated d' _ -> validRecursiveD d'+ _ -> Nothing - ExpectedType lqn disp -> fixNameDisp disp $- hang (text "[error] at" <+> pp (srcRange lqn))- 4 (fsep [ text "Expected a type named", quotes (pp (thing lqn))- , text "but found a value instead" ])+checkSameModule :: [DepName] -> RenameM ()+checkSameModule xs =+ 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+ _ -> pure ()+ where+ ms = [ (x,p) | NamedThing x <- xs, Declared p _ <- [ nameInfo x ] ] - FixityError o1 f1 o2 f2 disp -> fixNameDisp disp $- hang (text "[error] at" <+> pp (srcRange o1) <+> text "and" <+> pp (srcRange o2))- 4 (fsep [ text "The fixities of"- , nest 2 $ vcat- [ "•" <+> pp (thing o1) <+> parens (pp f1)- , "•" <+> pp (thing o2) <+> parens (pp f2) ]- , text "are not compatible."- , text "You may use explicit parentheses to disambiguate." ]) - InvalidConstraint ty disp -> fixNameDisp disp $- hang (text "[error]" <+> maybe empty (\r -> text "at" <+> pp r) (getLoc ty))- 4 (fsep [ pp ty, text "is not a valid constraint" ])-- MalformedBuiltin ty pn disp -> fixNameDisp disp $- hang (text "[error]" <+> maybe empty (\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 disp -> fixNameDisp disp $- hang (text "[error]" <+> maybe empty (\r -> text "at" <+> pp r) loc)- 4 (fsep [ text "built-in type", quotes (pp n), text "shadowed in", src ])-- OverlappingRecordUpdate xs ys disp -> fixNameDisp disp $- hang "[error] Overlapping record updates:"- 4 (vcat [ ppLab xs, ppLab ys ])- where- ppLab as = ppNestedSels (thing as) <+> "at" <+> pp (srcRange as)---- Warnings ----------------------------------------------------------------------data RenamerWarning- = SymbolShadowed Name [Name] NameDisp-- | UnusedName Name NameDisp- deriving (Show, Generic, NFData)--instance PP RenamerWarning where- ppPrec _ (SymbolShadowed new originals disp) = fixNameDisp disp $- hang (text "[warning] at" <+> loc)- 4 $ fsep [ text "This binding for" <+> backticks sym- , text "shadows the existing binding" <.> plural <+>- text "at" ]- $$ vcat (map (pp . nameLoc) originals)-- where- plural | length originals > 1 = char 's'- | otherwise = empty-- loc = pp (nameLoc new)- sym = pp new-- ppPrec _ (UnusedName x disp) = fixNameDisp disp $- hang (text "[warning] at" <+> pp (nameLoc x))- 4 (text "Unused name:" <+> pp x)+renameTopDecls' ::+ (NestedMods,ModPath) -> [TopDecl PName] -> RenameM [TopDecl Name]+renameTopDecls' info ds =+ do (ds1,deps) <- depGroup (traverse (renameWithMods info) ds) -data RenamerWarnings = RenamerWarnings- { renWarnNameDisp :: !NameDisp- , renWarnShadow :: Map Name (Set Name)- , renWarnUnused :: Set Name- }--noRenamerWarnings :: RenamerWarnings-noRenamerWarnings = RenamerWarnings- { renWarnNameDisp = mempty- , renWarnShadow = Map.empty- , renWarnUnused = Set.empty- }--addRenamerWarning :: RenamerWarning -> RenamerWarnings -> RenamerWarnings-addRenamerWarning w ws =- case w of- SymbolShadowed x xs d ->- ws { renWarnNameDisp = renWarnNameDisp ws <> d- , renWarnShadow = Map.insertWith Set.union x (Set.fromList xs)- (renWarnShadow ws)- }- UnusedName x d ->- ws { renWarnNameDisp = renWarnNameDisp ws <> d- , renWarnUnused = Set.insert x (renWarnUnused ws)- }--listRenamerWarnings :: RenamerWarnings -> [RenamerWarning]-listRenamerWarnings ws =- [ mk (UnusedName x) | x <- Set.toList (renWarnUnused ws) ] ++- [ mk (SymbolShadowed x (Set.toList xs))- | (x,xs) <- Map.toList (renWarnShadow ws) ]+ 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) ))+ ordered = stronglyConnComp (map toNode nameDs)+ fromSCC x =+ case x of+ AcyclicSCC (d,_) -> pure [d]+ CyclicSCC ds_xs ->+ let (rds,xs) = unzip ds_xs+ in case mapM valid rds of+ Nothing -> do record (InvalidDependency xs)+ pure rds+ Just bs ->+ do checkSameModule xs+ pure [Decl TopLevel+ { tlDoc = Nothing+ , tlExport = Public+ , tlValue = DRec bs+ }]+ where+ valid d = case d of+ Decl tl -> validRecursiveD (tlValue tl)+ _ -> Nothing+ rds <- mapM fromSCC ordered+ pure (concat (noNameDs:rds)) where- mk f = f (renWarnNameDisp ws)+ 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`) --- Renaming Monad -------------------------------------------------------------- -data RO = RO- { roLoc :: Range- , roMod :: !ModName- , roNames :: NamingEnv- , roDisp :: !NameDisp- }+ DModule tl -> any usesCtrs (mDecls m)+ where NestedModule m = tlValue tl+ DImport {} -> False+ Include {} -> bad "Include" -data RW = RW- { rwWarnings :: !RenamerWarnings- , rwErrors :: !(Seq.Seq RenamerError)- , rwSupply :: !Supply- , rwNameUseCount :: !(Map Name Int)- -- ^ How many times did we refer to each name.- -- Used to generate warnings for unused definitions.- }+ isValDecl d =+ case d of+ DLocated d' _ -> isValDecl d'+ DBind {} -> True+ DType {} -> False+ DProp {} -> False+ DRec {} -> True+ DSignature {} -> bad "DSignature"+ DFixity {} -> bad "DFixity"+ DPragma {} -> bad "DPragma"+ DPatBind {} -> bad "DPatBind" + bad msg = panic "renameTopDecls'" [msg] -newtype RenameM a = RenameM- { unRenameM :: ReaderT RO (StateT RW Lift) a }--instance S.Semigroup a => S.Semigroup (RenameM a) where- {-# INLINE (<>) #-}- a <> b =- do x <- a- y <- b- return (x S.<> y)--instance (S.Semigroup a, Monoid a) => Monoid (RenameM a) where- {-# INLINE mempty #-}- mempty = return mempty-- {-# INLINE mappend #-}- mappend = (S.<>)--instance Functor RenameM where- {-# INLINE fmap #-}- fmap f m = RenameM (fmap f (unRenameM m))--instance Applicative RenameM where- {-# INLINE pure #-}- pure x = RenameM (pure x)-- {-# INLINE (<*>) #-}- l <*> r = RenameM (unRenameM l <*> unRenameM r)+declName :: Decl Name -> Name+declName decl =+ case decl of+ DLocated d _ -> declName d+ DBind b -> thing (bName b)+ DType (TySyn x _ _ _) -> thing x+ DProp (PropSyn x _ _ _) -> thing x -instance Monad RenameM where- {-# INLINE return #-}- return x = RenameM (return x)+ DSignature {} -> bad "DSignature"+ DFixity {} -> bad "DFixity"+ DPragma {} -> bad "DPragma"+ DPatBind {} -> bad "DPatBind"+ DRec {} -> bad "DRec"+ where+ bad x = panic "declName" [x] - {-# INLINE (>>=) #-}- m >>= k = RenameM (unRenameM m >>= unRenameM . k)+topDeclName :: TopDecl Name -> Either (TopDecl Name) (TopDecl Name, 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))+ DModule d -> hasName (thing (mName m))+ where NestedModule m = tlValue d -instance FreshM RenameM where- liftSupply f = RenameM $ sets $ \ RW { .. } ->- let (a,s') = f rwSupply- rw' = RW { rwSupply = s', .. }- in a `seq` rw' `seq` (a, rw')+ DParameterConstraint ds ->+ case ds of+ [] -> noName+ _ -> Right (topDecl, ConstratintAt (fromJust (getLoc ds)))+ DImport {} -> noName -runRenamer :: Supply -> ModName -> NamingEnv -> RenameM a- -> (Either [RenamerError] (a,Supply),[RenamerWarning])-runRenamer s ns env m = (res, listRenamerWarnings warns)+ Include {} -> bad "Include" where- warns = foldr addRenamerWarning (rwWarnings rw)- (warnUnused ns env ro rw)+ noName = Left topDecl+ hasName n = Right (topDecl, NamedThing n)+ bad x = panic "topDeclName" [x] - (a,rw) = runM (unRenameM m) ro- RW { rwErrors = Seq.empty- , rwWarnings = noRenamerWarnings- , rwSupply = s- , rwNameUseCount = Map.empty- } - ro = RO { roLoc = emptyRange- , roNames = env- , roMod = ns- , roDisp = neverQualifyMod ns `mappend` toNameDisp env- }+-- | 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) - res | Seq.null (rwErrors rw) = Right (a,rwSupply rw)- | otherwise = Left (F.toList (rwErrors rw)) --- | Record an error. XXX: use a better name-record :: (NameDisp -> RenamerError) -> RenameM ()-record f = RenameM $- do RO { .. } <- ask- RW { .. } <- get- set RW { rwErrors = rwErrors Seq.|> f roDisp, .. } --- | Get the source range for wahtever we are currently renaming.-curLoc :: RenameM Range-curLoc = RenameM (roLoc `fmap` ask)---- | Annotate something with the current range.-located :: a -> RenameM (Located a)-located thing =- do srcRange <- curLoc- return Located { .. }---- | Do the given computation using the source code range from `loc` if any.-withLoc :: HasLoc loc => loc -> RenameM a -> RenameM a-withLoc loc m = RenameM $ case getLoc loc of-- Just range -> do- ro <- ask- local ro { roLoc = range } (unRenameM m)-- Nothing -> unRenameM m---- | Retrieve the name of the current module.-getNS :: RenameM ModName-getNS = RenameM (roMod `fmap` ask)---- | Shadow the current naming environment with some more names.-shadowNames :: BindsNames env => env -> RenameM a -> RenameM a-shadowNames = shadowNames' CheckAll--data EnvCheck = CheckAll -- ^ Check for overlap and shadowing- | CheckOverlap -- ^ Only check for overlap- | CheckNone -- ^ Don't check the environment- deriving (Eq,Show)---- | Shadow the current naming environment with some more names.-shadowNames' :: BindsNames env => EnvCheck -> env -> RenameM a -> RenameM a-shadowNames' check names m = do- do env <- liftSupply (namingEnv' names)- RenameM $- do ro <- ask- env' <- sets (checkEnv (roDisp ro) check env (roNames ro))- let ro' = ro { roNames = env' `shadowing` roNames ro }- local ro' (unRenameM m)--shadowNamesNS :: BindsNames (InModule env) => env -> RenameM a -> RenameM a-shadowNamesNS names m =- do ns <- getNS- shadowNames (InModule ns names) m+--------------------------------------------------------------------------------+-- Compute names coming through `open` statements. +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+ } --- | Generate warnings when the left environment shadows things defined in--- the right. Additionally, generate errors when two names overlap in the--- left environment.-checkEnv :: NameDisp -> EnvCheck -> NamingEnv -> NamingEnv -> RW -> (NamingEnv,RW)-checkEnv disp check l r rw- | check == CheckNone = (l',rw)- | otherwise = (l',rw'')+-- | 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.+ -} +{- | 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 - l' = l { neExprs = es, neTypes = ts } - (rw',es) = Map.mapAccumWithKey (step neExprs) rw (neExprs l)- (rw'',ts) = Map.mapAccumWithKey (step neTypes) rw' (neTypes l)+-------------------------------------------------------------------------------- - step prj acc k ns = (acc', [head ns])- where- acc' = acc- { rwWarnings =- if check == CheckAll- then case Map.lookup k (prj r) of- Nothing -> rwWarnings acc- Just os -> addRenamerWarning - (SymbolShadowed (head ns) os disp)- (rwWarnings acc) - else rwWarnings acc- , rwErrors = rwErrors acc Seq.>< containsOverlap disp ns- }+data WithMods f n = WithMods (NestedMods,ModPath) (f n) --- | Check the RHS of a single name rewrite for conflicting sources.-containsOverlap :: NameDisp -> [Name] -> Seq.Seq RenamerError-containsOverlap _ [_] = Seq.empty-containsOverlap _ [] = panic "Renamer" ["Invalid naming environment"]-containsOverlap disp ns = Seq.singleton (OverlappingSyms ns disp)+forgetMods :: WithMods f n -> f n+forgetMods (WithMods _ td) = td --- | Throw errors for any names that overlap in a rewrite environment.-checkNamingEnv :: NamingEnv -> ([RenamerError],[RenamerWarning])-checkNamingEnv env = (F.toList out, [])- where- out = Map.foldr check outTys (neExprs env)- outTys = Map.foldr check mempty (neTypes env)+renameWithMods ::+ Rename (WithMods f) => (NestedMods,ModPath) -> f PName -> RenameM (f Name)+renameWithMods info m = forgetMods <$> rename (WithMods info m) - disp = toNameDisp env - check ns acc = containsOverlap disp ns Seq.>< acc+instance Rename (WithMods TopDecl) where+ rename (WithMods info td) = WithMods info <$>+ 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 -recordUse :: Name -> RenameM ()-recordUse x = RenameM $ sets_ $ \rw ->- rw { rwNameUseCount = Map.insertWith (+) x 1 (rwNameUseCount rw) }+ 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 } +instance Rename ImpName where+ rename i =+ case i of+ ImpTop m -> pure (ImpTop m)+ ImpNested m -> ImpNested <$> resolveName NameUse NSModule m -warnUnused :: ModName -> NamingEnv -> RO -> RW -> [RenamerWarning]-warnUnused m0 env ro rw =- map warn- $ Map.keys- $ Map.filterWithKey keep- $ rwNameUseCount rw- where- warn x = UnusedName x (roDisp ro)- keep k n = n == 1 && isLocal k- oldNames = fst (visibleNames env)- isLocal nm = case nameInfo nm of- Declared m sys -> sys == UserName &&- m == m0 && nm `Set.notMember` oldNames- Parameter -> True+instance Rename (WithMods NestedModule) where+ rename (WithMods info (NestedModule m)) = WithMods info <$>+ do let (nested,mpath) = info+ 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+ -- nested modules properly+ (_inScope,m1) <- renameModule' nested env newMPath m+ pure (NestedModule m1 { mName = lnm { thing = n } }) --- Renaming -------------------------------------------------------------------- -class Rename f where- rename :: f PName -> RenameM (f Name)--renameModule :: Module PName -> RenameM (NamingEnv,Module Name)-renameModule m =- do env <- liftSupply (namingEnv' m)- -- NOTE: we explicitly hide shadowing errors here, by using shadowNames'- decls' <- shadowNames' CheckOverlap env (traverse rename (mDecls m))- let m1 = m { mDecls = decls' }- exports = modExports m1- mapM_ recordUse (eTypes exports)- return (env,m1)--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-- DParameterConstraint d -> DParameterConstraint <$> mapM renameLocated d- renameLocated :: Rename f => Located (f PName) -> RenameM (Located (f Name)) renameLocated x = do y <- rename (thing x)@@ -456,21 +470,30 @@ instance Rename PrimType where rename pt =- do x <- rnLocated renameType (primTName pt)- let (as,ps) = primTCts pt- (_,cts) <- renameQual as ps $ \as' ps' -> pure (as',ps')- pure pt { primTCts = cts, primTName = x }+ do x <- rnLocated (renameType NameBind) (primTName pt)+ depsOf (NamedThing (thing x))+ do let (as,ps) = primTCts pt+ (_,cts) <- renameQual as ps $ \as' ps' -> pure (as',ps') + -- 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+ -- about unused names.+ mapM_ (recordUse . tpName) (fst cts)++ pure pt { primTCts = cts, primTName = x }+ instance Rename ParameterType where rename a =- do n' <- rnLocated renameType (ptName a)+ do n' <- rnLocated (renameType NameBind) (ptName a) return a { ptName = n' } instance Rename ParameterFun where rename a =- do n' <- rnLocated renameVar (pfName a)- sig' <- renameSchema (pfSchema a)- return a { pfName = n', pfSchema = snd sig' }+ do n' <- rnLocated (renameVar NameBind) (pfName a)+ depsOf (NamedThing (thing n'))+ 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 $@@ -479,101 +502,95 @@ instance Rename Decl where rename d = case d of- DSignature ns sig -> DSignature <$> traverse (rnLocated renameVar) ns- <*> rename sig- DPragma ns p -> DPragma <$> traverse (rnLocated renameVar) ns- <*> pure p- DBind b -> DBind <$> rename b-- -- XXX we probably shouldn't see these at this point...- DPatBind pat e -> do (pe,pat') <- renamePat pat- shadowNames pe (DPatBind pat' <$> rename e)+ DBind b -> DBind <$> rename b DType syn -> DType <$> rename syn DProp syn -> DProp <$> rename syn DLocated d' r -> withLoc r $ DLocated <$> rename d' <*> pure r- DFixity{} -> panic "Renamer" ["Unexpected fixity declaration"- , show d] -instance Rename Newtype where- rename n = do- name' <- rnLocated renameType (nName n)- shadowNames (nParams n) $- do ps' <- traverse rename (nParams n)- body' <- traverse (traverse rename) (nBody n)- return Newtype { nName = name'- , nParams = ps'- , nBody = body' }+ DFixity{} -> panic "renaem" [ "DFixity" ]+ DSignature {} -> panic "rename" [ "DSignature" ]+ DPragma {} -> panic "rename" [ "DPragma" ]+ DPatBind {} -> panic "rename" [ "DPatBind " ]+ DRec {} -> panic "rename" [ "DRec" ] -renameVar :: PName -> RenameM Name-renameVar qn = do- ro <- RenameM ask- case Map.lookup qn (neExprs (roNames ro)) of- Just [n] -> return n- Just [] -> panic "Renamer" ["Invalid expression renaming environment"]- Just syms ->- do n <- located qn- record (MultipleSyms n syms)- return (head syms) - -- This is an unbound value. Record an error and invent a bogus real name- -- for it.- Nothing ->- do n <- located qn - case Map.lookup qn (neTypes (roNames ro)) of- -- types existed with the name of the value expected- Just _ -> record (ExpectedValue n)+instance Rename Newtype where+ rename n =+ shadowNames (nParams n) $+ do name' <- rnLocated (renameType NameBind) (nName n)+ depsOf (NamedThing (thing name')) $+ do ps' <- traverse rename (nParams n)+ body' <- traverse (traverse rename) (nBody n)+ return Newtype { nName = name'+ , nParams = ps'+ , nBody = body' } - -- the value is just missing- Nothing -> record (UnboundExpr n) - mkFakeName qn --- | Produce a name if one exists. Note that this includes situations where--- overlap exists, as it's just a query about anything being in scope. In the--- event that overlap does exist, an error will be recorded.-typeExists :: PName -> RenameM (Maybe Name)-typeExists pn =+-- | Try to resolve a name+resolveNameMaybe :: NameType -> Namespace -> PName -> RenameM (Maybe Name)+resolveNameMaybe nt expected qn = do ro <- RenameM ask- case Map.lookup pn (neTypes (roNames ro)) of- Just [n] -> recordUse n >> return (Just n)- Just [] -> panic "Renamer" ["Invalid type renaming environment"]- Just syms -> do n <- located pn- mapM_ recordUse syms- record (MultipleSyms n syms)- return (Just (head syms))- Nothing -> return Nothing+ let lkpIn here = Map.lookup qn (namespaceMap here (roNames ro))+ use = case expected of+ 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)) -renameType :: PName -> RenameM Name-renameType pn =- do mb <- typeExists pn- case mb of- Just n -> return n+ Nothing -> pure Nothing - -- This is an unbound value. Record an error and invent a bogus real name- -- for it.+-- | 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 n = Located { srcRange = roLoc ro, thing = pn }+ 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) - case Map.lookup pn (neExprs (roNames ro)) of+ -- the value is just missing+ [] -> record (UnboundName expected nm) - -- values exist with the same name, so throw a different error- Just _ -> record (ExpectedType n)+ mkFakeName expected qn - -- no terms with the same name, so the type is just unbound- Nothing -> record (UnboundType n) - mkFakeName pn+renameVar :: NameType -> PName -> RenameM Name+renameVar nt = resolveName nt NSValue +renameType :: NameType -> PName -> RenameM Name+renameType nt = resolveName nt NSType+++ -- | Assuming an error has been recorded already, construct a fake name that's -- not expected to make it out of the renamer.-mkFakeName :: PName -> RenameM Name-mkFakeName pn =+mkFakeName :: Namespace -> PName -> RenameM Name+mkFakeName ns pn = do ro <- RenameM ask- liftSupply (mkParameter (getIdent pn) (roLoc ro))+ liftSupply (mkParameter ns (getIdent pn) (roLoc ro)) -- | Rename a schema, assuming that none of its type variables are already in -- scope.@@ -593,7 +610,7 @@ ([TParam Name] -> [Prop Name] -> RenameM a) -> RenameM (NamingEnv, a) renameQual as ps k =- do env <- liftSupply (namingEnv' as)+ do env <- liftSupply (defsOf as) res <- shadowNames env $ do as' <- traverse rename as ps' <- traverse rename ps k as' ps'@@ -601,7 +618,7 @@ instance Rename TParam where rename TParam { .. } =- do n <- renameType tpName+ do n <- renameType NameBind tpName return TParam { tpName = n, .. } instance Rename Prop where@@ -616,7 +633,7 @@ TBit -> return TBit TNum c -> return (TNum c) TChar c -> return (TChar c)- TUser qn ps -> TUser <$> renameType qn <*> traverse rename ps+ TUser qn ps -> TUser <$> renameType NameUse qn <*> traverse rename ps TTyApp fs -> TTyApp <$> traverse (traverse rename) fs TRecord fs -> TRecord <$> traverse (traverse rename) fs TTuple fs -> TTuple <$> traverse rename fs@@ -628,7 +645,8 @@ b' <- rename b mkTInfix a' o' b' -mkTInfix :: Type Name -> (Located Name, Fixity) -> Type Name -> RenameM (Type Name)+mkTInfix ::+ Type Name -> (Located Name, Fixity) -> Type Name -> RenameM (Type Name) mkTInfix t@(TInfix x o1 f1 y) op@(o2,f2) z = case compareFixity f1 f2 of@@ -647,20 +665,21 @@ -- | Rename a binding. instance Rename Bind where- rename b = do- n' <- rnLocated renameVar (bName b)- mbSig <- traverse renameSchema (bSignature b)- shadowNames (fst `fmap` mbSig) $- do (patEnv,pats') <- renamePats (bParams b)- -- NOTE: renamePats will generate warnings, so we don't need to trigger- -- them again here.- e' <- shadowNames' CheckNone patEnv (rnLocated rename (bDef b))- return b { bName = n'- , bParams = pats'- , bDef = e'- , bSignature = snd `fmap` mbSig- , bPragmas = bPragmas b- }+ rename b =+ do n' <- rnLocated (renameVar NameBind) (bName b)+ depsOf (NamedThing (thing n'))+ do mbSig <- traverse renameSchema (bSignature b)+ shadowNames (fst `fmap` mbSig) $+ do (patEnv,pats') <- renamePats (bParams b)+ -- NOTE: renamePats will generate warnings,+ -- so we don't need to trigger them again here.+ e' <- shadowNames' CheckNone patEnv (rnLocated rename (bDef b))+ return b { bName = n'+ , bParams = pats'+ , bDef = e'+ , bSignature = snd `fmap` mbSig+ , bPragmas = bPragmas b+ } instance Rename BindDef where rename DPrim = return DPrim@@ -669,7 +688,7 @@ -- NOTE: this only renames types within the pattern. instance Rename Pattern where rename p = case p of- PVar lv -> PVar <$> rnLocated renameVar lv+ PVar lv -> PVar <$> rnLocated (renameVar NameBind) lv PWild -> pure PWild PTuple ps -> PTuple <$> traverse rename ps PRecord nps -> PRecord <$> traverse (traverse rename) nps@@ -702,12 +721,12 @@ instance Rename FunDesc where rename (FunDesc nm offset) =- do nm' <- traverse renameVar nm+ do nm' <- traverse (renameVar NameBind) nm pure (FunDesc nm' offset) instance Rename Expr where rename expr = case expr of- EVar n -> EVar <$> renameVar n+ EVar n -> EVar <$> renameVar NameUse n ELit l -> return (ELit l) ENeg e -> ENeg <$> rename e EComplement e -> EComplement@@ -724,6 +743,18 @@ <*> traverse rename n <*> rename e <*> traverse rename t+ EFromToBy isStrict s e b t ->+ EFromToBy isStrict+ <$> rename s+ <*> rename e+ <*> rename b+ <*> traverse rename t+ EFromToDownBy isStrict s e b t ->+ EFromToDownBy isStrict+ <$> rename s+ <*> rename e+ <*> rename b+ <*> traverse rename t EFromToLessThan s e t -> EFromToLessThan <$> rename s <*> rename e@@ -737,9 +768,8 @@ EApp f x -> EApp <$> rename f <*> rename x EAppT f ti -> EAppT <$> rename f <*> traverse rename ti EIf b t f -> EIf <$> rename b <*> rename t <*> rename f- EWhere e' ds -> do ns <- getNS- shadowNames (map (InModule ns) ds) $- EWhere <$> rename e' <*> traverse rename ds+ EWhere e' ds -> shadowNames (map (InModule Nothing) ds) $+ EWhere <$> rename e' <*> renameDecls ds ETyped e' ty -> ETyped <$> rename e' <*> rename ty ETypeVal ty -> ETypeVal<$> rename ty EFun desc ps e' -> do desc' <- rename desc@@ -810,14 +840,14 @@ renameOp :: Located PName -> RenameM (Located Name, Fixity) renameOp ln = withLoc ln $- do n <- renameVar (thing ln)+ do n <- renameVar NameUse (thing ln) fixity <- lookupFixity n return (ln { thing = n }, fixity) renameTypeOp :: Located PName -> RenameM (Located Name, Fixity) renameTypeOp ln = withLoc ln $- do n <- renameType (thing ln)+ do n <- renameType NameUse (thing ln) fixity <- lookupFixity n return (ln { thing = n }, fixity) @@ -859,8 +889,7 @@ return (pe,Match p' e') renameMatch (MatchLet b) =- do ns <- getNS- be <- liftSupply (namingEnv' (InModule ns b))+ do be <- liftSupply (defsOf (InModule Nothing b)) b' <- shadowNames be (rename b) return (be,MatchLet b') @@ -892,7 +921,8 @@ patternEnv = go where go (PVar Located { .. }) =- do n <- liftSupply (mkParameter (getIdent thing) srcRange)+ do n <- liftSupply (mkParameter NSValue (getIdent thing) srcRange)+ -- XXX: for deps, we should record a use return (singletonE thing n) go PWild = return mempty@@ -919,7 +949,7 @@ typeEnv TChar{} = return mempty typeEnv (TUser pn ps) =- do mb <- typeExists pn+ do mb <- resolveNameMaybe NameUse NSType pn case mb of -- The type is already bound, don't introduce anything.@@ -931,15 +961,15 @@ -- of the type of the pattern. | null ps -> do loc <- curLoc- n <- liftSupply (mkParameter (getIdent pn) loc)+ n <- liftSupply (mkParameter NSType (getIdent pn) loc) return (singletonT 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 (UnboundType (Located loc pn))- n <- liftSupply (mkParameter (getIdent pn) loc)+ record (UnboundName NSType (Located loc pn))+ n <- liftSupply (mkParameter NSType (getIdent pn) loc) return (singletonT pn n) typeEnv (TRecord fs) = bindTypes (map snd (recordElements fs))@@ -961,18 +991,17 @@ instance Rename Match where rename m = case m of Match p e -> Match <$> rename p <*> rename e- MatchLet b -> shadowNamesNS b (MatchLet <$> rename b)+ MatchLet b -> shadowNames (InModule Nothing b) (MatchLet <$> rename b) instance Rename TySyn where rename (TySyn n f ps ty) =- shadowNames ps $ TySyn <$> rnLocated renameType n- <*> pure f- <*> traverse rename ps- <*> rename ty+ shadowNames ps+ do n' <- rnLocated (renameType NameBind) n+ depsOf (NamedThing (thing n')) $+ TySyn n' <$> pure f <*> traverse rename ps <*> rename ty instance Rename PropSyn where rename (PropSyn n f ps cs) =- shadowNames ps $ PropSyn <$> rnLocated renameType n- <*> pure f- <*> traverse rename ps- <*> traverse rename cs+ shadowNames ps+ do n' <- rnLocated (renameType NameBind) n+ PropSyn n' <$> pure f <*> traverse rename ps <*> traverse rename cs
+ src/Cryptol/ModuleSystem/Renamer/Error.hs view
@@ -0,0 +1,205 @@+-- |+-- Module : Cryptol.ModuleSystem.Renamer+-- Copyright : (c) 2013-2016 Galois, Inc.+-- License : BSD3+-- Maintainer : cryptol@galois.com+-- Stability : provisional+-- Portability : portable++{-# Language DeriveGeneric, DeriveAnyClass #-}+{-# Language OverloadedStrings #-}+module Cryptol.ModuleSystem.Renamer.Error where++import Cryptol.ModuleSystem.Name+import Cryptol.Parser.AST+import Cryptol.Parser.Position+import Cryptol.Parser.Selector(ppNestedSels)+import Cryptol.Utils.PP++import GHC.Generics (Generic)+import Control.DeepSeq++import Prelude ()+import Prelude.Compat++-- Errors ----------------------------------------------------------------------++data RenamerError+ = MultipleSyms (Located PName) [Name]+ -- ^ Multiple imported symbols contain this name++ | UnboundName Namespace (Located PName)+ -- ^ Some name not bound to any definition++ | OverlappingSyms [Name]+ -- ^ An environment has produced multiple overlapping symbols++ | WrongNamespace Namespace Namespace (Located PName)+ -- ^ expected, actual.+ -- When a name is missing from the expected namespace, but exists in another++ | 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)+++-- We use this because parameter constrstaints have no names+data DepName = NamedThing Name+ | ConstratintAt Range -- ^ identifed by location in source+ deriving (Eq,Ord,Show,Generic,NFData)++depNameLoc :: DepName -> Range+depNameLoc x =+ case x of+ NamedThing n -> nameLoc n+ ConstratintAt r -> r+ +++instance PP RenamerError where+ ppPrec _ e = case e of++ MultipleSyms lqn qns ->+ hang (text "[error] at" <+> pp (srcRange lqn))+ 4 $ (text "Multiple definitions for symbol:" <+> pp (thing lqn))+ $$ vcat (map ppLocName qns)++ UnboundName ns lqn ->+ hang (text "[error] at" <+> pp (srcRange lqn))+ 4 (something <+> "not in scope:" <+> pp (thing lqn))+ where+ something = case ns of+ NSValue -> "Value"+ NSType -> "Type"+ NSModule -> "Module"++ OverlappingSyms qns ->+ hang (text "[error]")+ 4 $ text "Overlapping symbols defined:"+ $$ vcat (map ppLocName qns)++ WrongNamespace expected actual lqn ->+ hang ("[error] at" <+> pp (srcRange lqn ))+ 4 (fsep $+ [ "Expected a", sayNS expected, "named", quotes (pp (thing lqn))+ , "but found a", sayNS actual, "instead"+ ] ++ suggestion)+ where+ sayNS ns = case ns of+ NSValue -> "value"+ NSType -> "type"+ NSModule -> "module"+ suggestion =+ case (expected,actual) of++ (NSValue,NSType) ->+ ["Did you mean `(" <.> pp (thing lqn) <.> text")?"]+ _ -> []++ FixityError o1 f1 o2 f2 ->+ hang (text "[error] at" <+> pp (srcRange o1) <+> text "and" <+> pp (srcRange o2))+ 4 (vsep [ text "The fixities of"+ , indent 2 $ vcat+ [ "•" <+> pp (thing o1) <+> parens (pp f1)+ , "•" <+> pp (thing o2) <+> parens (pp f2) ]+ , 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 ])+ where+ ppLab as = ppNestedSels (thing as) <+> "at" <+> pp (srcRange as)++ InvalidDependency ds ->+ hang "[error] Invalid recursive dependency:"+ 4 (vcat [ "•" <+> pp x <.> ", defined at" <+> ppR (depNameLoc x)+ | x <- ds ])+ where ppR r = pp (from r) <.> "--" <.> pp (to r)++instance PP DepName where+ ppPrec _ d =+ case d of+ ConstratintAt r -> "constraint at" <+> pp r+ NamedThing n ->+ case nameNamespace n of+ NSModule -> "submodule" <+> pp n+ NSType -> "type" <+> pp n+ NSValue -> pp n++++-- Warnings --------------------------------------------------------------------++data RenamerWarning+ = SymbolShadowed PName Name [Name]+ | UnusedName Name+ deriving (Show, Generic, NFData)++instance Eq RenamerWarning where+ x == y = compare x y == EQ++-- used to determine in what order ot 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++ where+ byStart = from . nameLoc+++instance PP RenamerWarning where+ ppPrec _ (SymbolShadowed k x os) =+ hang (text "[warning] at" <+> loc)+ 4 $ fsep [ "This binding for" <+> backticks (pp k)+ , "shadows the existing binding" <.> plural+ , text "at" ]+ $$ vcat (map (pp . nameLoc) os)++ where+ plural | length os > 1 = char 's'+ | otherwise = mempty++ loc = pp (nameLoc x)++ ppPrec _ (UnusedName x) =+ hang (text "[warning] at" <+> pp (nameLoc x))+ 4 (text "Unused name:" <+> pp x)+++
+ src/Cryptol/ModuleSystem/Renamer/Monad.hs view
@@ -0,0 +1,342 @@+-- |+-- Module : Cryptol.ModuleSystem.Renamer+-- Copyright : (c) 2013-2016 Galois, Inc.+-- License : BSD3+-- Maintainer : cryptol@galois.com+-- Stability : provisional+-- Portability : portable++{-# Language RecordWildCards #-}+{-# Language FlexibleContexts #-}+{-# Language BlockArguments #-}+module Cryptol.ModuleSystem.Renamer.Monad where++import Data.List(sort)+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.ModuleSystem.Name+import Cryptol.ModuleSystem.NamingEnv+import Cryptol.ModuleSystem.Interface+import Cryptol.Parser.AST+import Cryptol.Parser.Position+import Cryptol.Utils.Panic (panic)+import Cryptol.Utils.Ident(modPathCommon)++import Cryptol.ModuleSystem.Renamer.Error++-- | Indicates if a name is in a binding poisition or a use site+data NameType = NameBind | NameUse++-- | Information needed to do some renaming.+data RenamerInfo = RenamerInfo+ { 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+ }++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+ , roNestedMods :: Map ModPath Name+ }++data RW = RW+ { rwWarnings :: ![RenamerWarning]+ , rwErrors :: !(Seq.Seq RenamerError)+ , rwSupply :: !Supply+ , rwNameUseCount :: !(Map Name Int)+ -- ^ How many times did we refer to each name.+ -- Used to generate warnings for unused definitions.++ , rwCurrentDeps :: Set Name+ -- ^ keeps track of names *used* by something.+ -- see 'depsOf'++ , rwDepGraph :: Map DepName (Set Name)+ -- ^ keeps track of the dependencies for things.+ -- see 'depsOf'++ , rwExternalDeps :: !IfaceDecls+ -- ^ Info about imported things+ }++++instance S.Semigroup a => S.Semigroup (RenameM a) where+ {-# INLINE (<>) #-}+ a <> b =+ do x <- a+ y <- b+ return (x S.<> y)++instance (S.Semigroup a, Monoid a) => Monoid (RenameM a) where+ {-# INLINE mempty #-}+ mempty = return mempty++ {-# INLINE mappend #-}+ mappend = (S.<>)++instance Functor RenameM where+ {-# INLINE fmap #-}+ fmap f m = RenameM (fmap f (unRenameM m))++instance Applicative RenameM where+ {-# INLINE pure #-}+ pure x = RenameM (pure x)++ {-# INLINE (<*>) #-}+ l <*> r = RenameM (unRenameM l <*> unRenameM r)++instance Monad RenameM where+ {-# INLINE return #-}+ return x = RenameM (return x)++ {-# INLINE (>>=) #-}+ m >>= k = RenameM (unRenameM m >>= unRenameM . k)++instance FreshM RenameM where+ liftSupply f = RenameM $ sets $ \ RW { .. } ->+ let (a,s') = f rwSupply+ rw' = RW { rwSupply = s', .. }+ in a `seq` rw' `seq` (a, rw')+++runRenamer :: RenamerInfo -> RenameM a+ -> ( Either [RenamerError] (a,Supply)+ , [RenamerWarning]+ )+runRenamer info m = (res, warns)+ where+ warns = sort (rwWarnings rw ++ warnUnused (renContext info) (renEnv info) rw)++ (a,rw) = runM (unRenameM m) ro+ RW { rwErrors = Seq.empty+ , rwWarnings = []+ , rwSupply = renSupply info+ , rwNameUseCount = Map.empty+ , rwExternalDeps = mempty+ , rwCurrentDeps = Set.empty+ , rwDepGraph = Map.empty+ }++ ro = RO { roLoc = emptyRange+ , roNames = renEnv info+ , roIfaces = renIfaces info+ , roCurMod = renContext info+ , roNestedMods = Map.empty+ }++ res | Seq.null (rwErrors rw) = Right (a,rwSupply rw)+ | otherwise = Left (F.toList (rwErrors rw))+++setCurMod :: ModPath -> RenameM a -> RenameM a+setCurMod mpath (RenameM m) =+ RenameM $ mapReader (\ro -> ro { roCurMod = mpath }) m++getCurMod :: RenameM ModPath+getCurMod = RenameM $ asks roCurMod++getNamingEnv :: RenameM NamingEnv+getNamingEnv = RenameM (asks roNames)+++setNestedModule :: Map ModPath Name -> RenameM a -> RenameM a+setNestedModule mp (RenameM m) =+ RenameM $ mapReader (\ro -> ro { roNestedMods = mp }) m++nestedModuleOrig :: ModPath -> RenameM (Maybe Name)+nestedModuleOrig x = RenameM (asks (Map.lookup x . roNestedMods))+++-- | Record an error. XXX: use a better name+record :: RenamerError -> RenameM ()+record f = RenameM $+ do RW { .. } <- get+ set RW { rwErrors = rwErrors Seq.|> f, .. }++collectIfaceDeps :: RenameM a -> RenameM (IfaceDecls,a)+collectIfaceDeps (RenameM m) =+ RenameM+ do ds <- sets \s -> (rwExternalDeps s, s { rwExternalDeps = mempty })+ a <- m+ ds' <- sets \s -> (rwExternalDeps s, s { rwExternalDeps = ds })+ pure (ds',a)++-- | Rename something. All name uses in the sub-computation are assumed+-- to be dependenices of the thing.+depsOf :: DepName -> RenameM a -> RenameM a+depsOf x (RenameM m) = RenameM+ do ds <- sets \rw -> (rwCurrentDeps rw, rw { rwCurrentDeps = Set.empty })+ a <- m+ sets_ \rw ->+ rw { rwCurrentDeps = Set.union (rwCurrentDeps rw) ds+ , rwDepGraph = Map.insert x (rwCurrentDeps rw) (rwDepGraph rw)+ }+ 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+-- be used to order the group members in dependency order.+depGroup :: RenameM a -> RenameM (a, Map DepName (Set Name))+depGroup (RenameM m) = RenameM+ do ds <- sets \rw -> (rwDepGraph rw, rw { rwDepGraph = Map.empty })+ a <- m+ ds1 <- sets \rw -> (rwDepGraph rw, rw { rwDepGraph = ds })+ pure (a,ds1)++-- | Get the source range for wahtever we are currently renaming.+curLoc :: RenameM Range+curLoc = RenameM (roLoc `fmap` ask)++-- | Annotate something with the current range.+located :: a -> RenameM (Located a)+located thing =+ do srcRange <- curLoc+ return Located { .. }++-- | Do the given computation using the source code range from `loc` if any.+withLoc :: HasLoc loc => loc -> RenameM a -> RenameM a+withLoc loc m = RenameM $ case getLoc loc of++ Just range -> do+ ro <- ask+ local ro { roLoc = range } (unRenameM m)++ Nothing -> unRenameM m+++-- | Shadow the current naming environment with some more names.+shadowNames :: BindsNames env => env -> RenameM a -> RenameM a+shadowNames = shadowNames' CheckAll++data EnvCheck = CheckAll -- ^ Check for overlap and shadowing+ | CheckOverlap -- ^ Only check for overlap+ | CheckNone -- ^ Don't check the environment+ deriving (Eq,Show)++-- | Shadow the current naming environment with some more names.+shadowNames' :: BindsNames env => EnvCheck -> env -> RenameM a -> RenameM a+shadowNames' check names m = do+ do env <- liftSupply (defsOf names)+ RenameM $+ do ro <- ask+ env' <- sets (checkEnv check env (roNames ro))+ let ro' = ro { roNames = env' `shadowing` roNames ro }+ 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) }+ {- NOTE: we don't distinguish between bindings and uses here, because+ the situation is complicated by the pattern signatures where the first+ "use" site is actually the binding site. Instead we just count them all, and+ something is considered unused if it is used only once (i.e, just the+ binding site) -}++-- | Mark something as a dependency. This is similar but different from+-- `recordUse`, in particular:+-- * We only record use sites, not bindings+-- * We record all namespaces, not just types+-- * We only keep track of actual uses mentioned in the code.+-- Otoh, `recordUse` also considers exported entities to be used.+-- * If we depend on a name from a sibling submodule we add a dependency on+-- the module in our common ancestor. Examples:+-- - @A::B::x@ depends on @A::B::C::D::y@, @x@ depends on @A::B::C@+-- - @A::B::x@ depends on @A::P::Q::y@@, @x@ depends on @A::P@++addDep :: Name -> RenameM ()+addDep x =+ do cur <- getCurMod+ deps <- case nameInfo x of+ Declared m _ | Just (c,_,i:_) <- modPathCommon cur m ->+ do mb <- nestedModuleOrig (Nested c i)+ pure case mb of+ Just y -> Set.fromList [x,y]+ Nothing -> Set.singleton x+ _ -> pure (Set.singleton x)+ RenameM $+ sets_ \rw -> rw { rwCurrentDeps = Set.union deps (rwCurrentDeps rw) }+++warnUnused :: ModPath -> NamingEnv -> RW -> [RenamerWarning]+warnUnused m0 env rw =+ map warn+ $ 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)+ isLocal nm = case nameInfo nm of+ Declared m sys -> sys == UserName &&+ m == m0 && nm `Set.notMember` oldNames+ Parameter -> 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++
src/Cryptol/Parser.y view
@@ -35,6 +35,7 @@ import Cryptol.Parser.AST import Cryptol.Parser.Position import Cryptol.Parser.LexerUtils hiding (mkIdent)+import Cryptol.Parser.Token import Cryptol.Parser.ParserUtils import Cryptol.Parser.Unlit(PreProc(..), guessPreProc) import Cryptol.Utils.Ident(paramInstModName)@@ -43,7 +44,7 @@ import Paths_cryptol } -{- state 196 contains 1 shift/reduce conflicts.+{- state 202 contains 1 shift/reduce conflicts. `_` identifier conflicts with `_` in record update. We have `_` as an identifier for the cases where we parse types as expressions, for example `[ 12 .. _ ]`.@@ -77,12 +78,15 @@ 'type' { Located $$ (Token (KW KW_type ) _)} 'newtype' { Located $$ (Token (KW KW_newtype) _)} 'module' { Located $$ (Token (KW KW_module ) _)}+ 'submodule' { Located $$ (Token (KW KW_submodule ) _)} 'where' { Located $$ (Token (KW KW_where ) _)} 'let' { Located $$ (Token (KW KW_let ) _)} 'if' { Located $$ (Token (KW KW_if ) _)} 'then' { Located $$ (Token (KW KW_then ) _)} 'else' { Located $$ (Token (KW KW_else ) _)} '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) _)}@@ -94,8 +98,10 @@ '..' { Located $$ (Token (Sym DotDot ) _)} '...' { Located $$ (Token (Sym DotDotDot) _)} '..<' { Located $$ (Token (Sym DotDotLt) _)}+ '..>' { Located $$ (Token (Sym DotDotGt) _)} '|' { Located $$ (Token (Sym Bar ) _)} '<' { Located $$ (Token (Sym Lt ) _)}+ '>' { Located $$ (Token (Sym Gt ) _)} '(' { Located $$ (Token (Sym ParenL ) _)} ')' { Located $$ (Token (Sym ParenR ) _)}@@ -158,27 +164,27 @@ %% -vmodule :: { Module PName }- : 'module' modName 'where' 'v{' vmod_body 'v}' { mkModule $2 $5 }- | 'module' modName '=' modName 'where' 'v{' vmod_body 'v}'- { mkModuleInstance $2 $4 $7 }- | 'v{' vmod_body 'v}' { mkAnonymousModule $2 }+vmodule :: { Module PName }+ : 'module' module_def { $2 }+ | 'v{' vmod_body 'v}' { mkAnonymousModule $2 } -vmod_body :: { ([Located Import], [TopDecl PName]) }- : vimports 'v;' vtop_decls { (reverse $1, reverse $3) }- | vimports ';' vtop_decls { (reverse $1, reverse $3) }- | vimports { (reverse $1, []) }- | vtop_decls { ([], reverse $1) }- | {- empty -} { ([], []) } -vimports :: { [Located Import] }- : vimports 'v;' import { $3 : $1 }- | vimports ';' import { $3 : $1 }- | import { [$1] }+module_def :: { Module PName } + : modName 'where'+ 'v{' vmod_body 'v}' { mkModule $1 $4 }++ | modName '=' modName 'where'+ 'v{' vmod_body 'v}' { mkModuleInstance $1 $3 $6 }++vmod_body :: { [TopDecl PName] }+ : vtop_decls { reverse $1 }+ | {- empty -} { [] }++ -- XXX replace rComb with uses of at-import :: { Located Import }- : 'import' modName mbAs mbImportSpec+import :: { Located (ImportG (ImpName PName)) }+ : 'import' impName mbAs mbImportSpec { Located { srcRange = rComb $1 $ fromMaybe (srcRange $2) $ msum [ fmap srcRange $4@@ -191,6 +197,11 @@ } } } +impName :: { Located (ImpName PName) }+ : 'submodule' qname { ImpNested `fmap` $2 }+ | modName { ImpTop `fmap` $1 }++ mbAs :: { Maybe (Located ModName) } : 'as' modName { Just $2 } | {- empty -} { Nothing }@@ -242,6 +253,9 @@ | prim_bind { $1 } | private_decls { $1 } | parameter_decls { $1 }+ | mbDoc 'submodule'+ module_def {% ((:[]) . exportModule $1) `fmap` mkNested $3 }+ | import { [DImport $1] } top_decl :: { [TopDecl PName] } : decl { [Decl (TopLevel {tlExport = Public, tlValue = $1 })] }@@ -303,6 +317,7 @@ , bInfix = True , bFixity = Nothing , bDoc = Nothing+ , bExport = Public } } | 'type' name '=' type {% at ($1,$4) `fmap` mkTySyn $2 [] $4 }@@ -323,10 +338,49 @@ | 'infix' NUM ops {% mkFixity NonAssoc $2 (reverse $3) } | error {% expected "a declaration" } +let_decls :: { [Decl PName] }+ : let_decl { [$1] }+ | let_decl ';' { [$1] }+ | let_decl ';' let_decls { ($1:$3) }+ let_decl :: { Decl PName }- : 'let' ipat '=' expr { at ($2,$4) $ DPatBind $2 $4 }- | 'let' name apats_indices '=' expr { at ($2,$5) $ mkIndexedDecl $2 $3 $5 }+ : 'let' ipat '=' expr { at ($2,$4) $ DPatBind $2 $4 }+ | 'let' var apats_indices '=' expr { at ($2,$5) $ mkIndexedDecl $2 $3 $5 }+ | 'let' '(' op ')' '=' expr { at ($2,$6) $ DPatBind (PVar $3) $6 }+ | 'let' apat pat_op apat '=' expr+ { at ($2,$6) $+ DBind $ Bind { bName = $3+ , bParams = [$2,$4]+ , bDef = at $6 (Located emptyRange (DExpr $6))+ , bSignature = Nothing+ , bPragmas = []+ , bMono = False+ , bInfix = True+ , bFixity = Nothing+ , bDoc = Nothing+ , bExport = Public+ } } + | '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 }++ | '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) }@@ -380,7 +434,7 @@ repl :: { ReplInput PName } : expr { ExprInput $1 }- | let_decl { LetInput $1 }+ | let_decls { LetInput $1 } | {- empty -} { EmptyInput } @@ -407,7 +461,7 @@ | '~' { Located $1 $ mkUnqual $ mkInfix "~" } | '^^' { Located $1 $ mkUnqual $ mkInfix "^^" } | '<' { Located $1 $ mkUnqual $ mkInfix "<" }-+ | '>' { Located $1 $ mkUnqual $ mkInfix ">" } other_op :: { LPName } : OP { let Token (Op (Other [] str)) _ = thing $1@@ -576,6 +630,14 @@ | expr '..' '<' expr {% eFromToLessThan $2 $1 $4 } | expr '..<' expr {% eFromToLessThan $2 $1 $3 } + | expr '..' expr 'by' expr {% eFromToBy $2 $1 $3 $5 False }+ | expr '..' '<' expr 'by' expr {% eFromToBy $2 $1 $4 $6 True }+ | expr '..<' expr 'by' expr {% eFromToBy $2 $1 $3 $5 True }++ | expr '..' expr 'down' 'by' expr {% eFromToDownBy $2 $1 $3 $6 False }+ | expr '..' '>' expr 'down' 'by' expr {% eFromToDownBy $2 $1 $4 $7 True }+ | expr '..>' expr 'down' 'by' expr {% eFromToDownBy $2 $1 $3 $6 True }+ | expr '...' { EInfFrom $1 Nothing } | expr ',' expr '...' { EInfFrom $1 (Just $3) } @@ -720,7 +782,6 @@ | 'private' { Located { srcRange = $1, thing = mkIdent "private" } } | 'as' { Located { srcRange = $1, thing = mkIdent "as" } } | 'hiding' { Located { srcRange = $1, thing = mkIdent "hiding" } }- name :: { LPName } : ident { fmap mkUnqual $1 }
src/Cryptol/Parser/AST.hs view
@@ -37,7 +37,10 @@ , psFixity -- * Declarations- , Module(..)+ , Module+ , ModuleG(..)+ , mImports+ , mSubmoduleImports , Program(..) , TopDecl(..) , Decl(..)@@ -50,11 +53,12 @@ , Pragma(..) , ExportType(..) , TopLevel(..)- , Import(..), ImportSpec(..)+ , Import, ImportG(..), ImportSpec(..), ImpName(..) , Newtype(..) , PrimType(..) , ParameterType(..) , ParameterFun(..)+ , NestedModule(..) -- * Interactive , ReplInput(..)@@ -119,15 +123,39 @@ deriving (Show) -- | A parsed module.-data Module name = Module- { mName :: Located ModName -- ^ Name of the module+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+ -- , mImports :: [Located Import] -- ^ Imports for the module , mDecls :: [TopDecl name] -- ^ Declartions for the module } deriving (Show, Generic, NFData) +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]+ ] +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]+ ]++++type Module = ModuleG ModName+++newtype NestedModule name = NestedModule (ModuleG name name)+ deriving (Show,Generic,NFData)++ modRange :: Module name -> Range modRange m = rCombs $ catMaybes [ getLoc (mName m)@@ -146,12 +174,21 @@ | DParameterConstraint [Located (Prop name)] -- ^ @parameter type constraint (fin T)@ | DParameterFun (ParameterFun name) -- ^ @parameter someVal : [256]@+ | DModule (TopLevel (NestedModule name)) -- ^ Nested module+ | DImport (Located (ImportG (ImpName name))) -- ^ An import declaration deriving (Show, Generic, NFData) +data ImpName name =+ ImpTop ModName+ | ImpNested name+ deriving (Show, Generic, NFData)+ data Decl name = DSignature [Located name] (Schema name) | DFixity !Fixity [Located name] | DPragma [Located name] Pragma | DBind (Bind name)+ | DRec [Bind name]+ -- ^ A group of recursive bindings, introduced by the renamer. | DPatBind (Pattern name) (Expr name) | DType (TySyn name) | DProp (PropSyn name)@@ -178,16 +215,15 @@ -- | An import declaration.-data Import = Import { iModule :: !ModName- , iAs :: Maybe ModName- , iSpec :: Maybe ImportSpec- } deriving (Eq, Show, Generic, NFData)+data ImportG mname = Import+ { iModule :: !mname+ , iAs :: Maybe ModName+ , iSpec :: Maybe ImportSpec+ } deriving (Eq, Show, Generic, NFData) +type Import = ImportG ModName+ -- | The list of names following an import.------ INVARIANT: All of the 'Name' entries in the list are expected to be--- unqualified names; the 'QName' or 'NewName' constructors should not be--- present. data ImportSpec = Hiding [Ident] | Only [Ident] deriving (Eq, Show, Generic, NFData)@@ -234,6 +270,7 @@ , bPragmas :: [Pragma] -- ^ Optional pragmas , bMono :: Bool -- ^ Is this a monomorphic binding , bDoc :: Maybe Text -- ^ Optional doc string+ , bExport :: !ExportType } deriving (Eq, Generic, NFData, Functor, Show) type LBindDef = Located (BindDef PName)@@ -263,7 +300,7 @@ -- | Input at the REPL, which can be an expression, a @let@ -- statement, or empty (possibly a comment). data ReplInput name = ExprInput (Expr name)- | LetInput (Decl name)+ | LetInput [Decl name] | EmptyInput deriving (Eq, Show) @@ -314,6 +351,11 @@ | EList [Expr n] -- ^ @ [1,2,3] @ | EFromTo (Type n) (Maybe (Type n)) (Type n) (Maybe (Type n)) -- ^ @ [1, 5 .. 117 : t] @+ | EFromToBy Bool (Type n) (Type n) (Type n) (Maybe (Type n))+ -- ^ @ [1 .. 10 by 2 : t ] @++ | EFromToDownBy Bool (Type n) (Type n) (Type n) (Maybe (Type n))+ -- ^ @ [10 .. 1 down by 2 : t ] @ | EFromToLessThan (Type n) (Type n) (Maybe (Type n)) -- ^ @ [ 1 .. < 10 : t ] @ @@ -482,14 +524,17 @@ getLoc = getLoc . tlValue instance HasLoc (TopDecl name) where- getLoc td = case td of- Decl tld -> getLoc tld- DPrimType pt -> getLoc pt- TDNewtype n -> getLoc n- Include lfp -> getLoc lfp- DParameterType d -> getLoc d- DParameterFun d -> getLoc d- DParameterConstraint d -> getLoc d+ getLoc td =+ case td of+ Decl tld -> getLoc tld+ DPrimType pt -> getLoc pt+ TDNewtype n -> getLoc n+ Include lfp -> getLoc lfp+ DParameterType d -> getLoc d+ DParameterFun d -> getLoc d+ DParameterConstraint d -> getLoc d+ DModule d -> getLoc d+ DImport d -> getLoc d instance HasLoc (PrimType name) where getLoc pt = Just (rComb (srcRange (primTName pt)) (srcRange (primTKind pt)))@@ -500,7 +545,7 @@ instance HasLoc (ParameterFun name) where getLoc a = getLoc (pfName a) -instance HasLoc (Module name) where+instance HasLoc (ModuleG mname name) where getLoc m | null locs = Nothing | otherwise = Just (rCombs locs)@@ -510,6 +555,9 @@ , getLoc (mDecls m) ] +instance HasLoc (NestedModule name) where+ getLoc (NestedModule m) = getLoc m+ instance HasLoc (Newtype name) where getLoc n | null locs = Nothing@@ -537,11 +585,25 @@ ppNamed' :: PP a => String -> (Ident, (Range, a)) -> Doc ppNamed' s (i,(_,v)) = pp i <+> text s <+> pp v -instance (Show name, PPName name) => PP (Module name) where- ppPrec _ m = text "module" <+> ppL (mName m) <+> text "where"- $$ vcat (map ppL (mImports m))- $$ vcat (map pp (mDecls m)) ++instance (Show name, PPName mname, PPName name) => PP (ModuleG mname name) where+ ppPrec _ = ppModule 0++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+ where+ body = vcat (map ppL (mImports m))+ $$ vcat (map pp (mDecls m))++++instance (Show name, PPName name) => PP (NestedModule name) where+ ppPrec _ (NestedModule m) = ppModule 2 m++ instance (Show name, PPName name) => PP (Program name) where ppPrec _ (Program ds) = vcat (map pp ds) @@ -556,10 +618,12 @@ DParameterType d -> pp d DParameterConstraint d -> "parameter" <+> "type" <+> "constraint" <+> prop- where prop = case map pp d of+ where prop = case map (pp . thing) d of [x] -> x [] -> "()"- xs -> parens (hsep (punctuate comma xs))+ xs -> nest 1 (parens (commaSepFill xs))+ DModule d -> pp d+ DImport i -> pp (thing i) instance (Show name, PPName name) => PP (PrimType name) where ppPrec _ pt =@@ -580,6 +644,7 @@ DSignature xs s -> commaSep (map ppL xs) <+> text ":" <+> pp s DPatBind p e -> pp p <+> text "=" <+> pp e DBind b -> ppPrec n b+ DRec bs -> nest 2 (vcat ("recursive" : map (ppPrec n) bs)) DFixity f ns -> ppFixity f ns DPragma xs p -> ppPragma xs p DType ts -> ppPrec n ts@@ -592,16 +657,22 @@ ppFixity (Fixity NonAssoc i) ns = text "infix" <+> int i <+> commaSep (map pp ns) instance PPName name => PP (Newtype name) where- ppPrec _ nt = hsep- [ text "newtype", ppL (nName nt), hsep (map pp (nParams nt)), char '='- , braces (commaSep (map (ppNamed' ":") (displayFields (nBody nt)))) ]+ ppPrec _ nt = nest 2 $ sep+ [ fsep $ [text "newtype", ppL (nName nt)] ++ map pp (nParams nt) ++ [char '=']+ , ppRecord (map (ppNamed' ":") (displayFields (nBody nt)))+ ] -instance PP Import where- ppPrec _ d = text "import" <+> sep [ pp (iModule d), mbAs, mbSpec ]+instance PP mname => PP (ImportG mname) where+ ppPrec _ d = text "import" <+> sep ([pp (iModule d)] ++ mbAs ++ mbSpec) where- mbAs = maybe empty (\ name -> text "as" <+> pp name ) (iAs d)+ mbAs = maybe [] (\ name -> [text "as" <+> pp name]) (iAs d)+ mbSpec = maybe [] (\x -> [pp x]) (iSpec d) - mbSpec = maybe empty pp (iSpec d)+instance PP name => PP (ImpName name) where+ ppPrec _ nm =+ case nm of+ ImpTop x -> pp x+ ImpNested x -> "submodule" <+> pp x instance PP ImportSpec where ppPrec _ s = case s of@@ -623,16 +694,16 @@ <+> text "*/" instance (Show name, PPName name) => PP (Bind name) where- ppPrec _ b = sig $$ vcat [ ppPragma [f] p | p <- bPragmas b ] $$- hang (def <+> eq) 4 (pp (thing (bDef b)))+ ppPrec _ b = vcat (sig ++ [ ppPragma [f] p | p <- bPragmas b ] +++ [hang (def <+> eq) 4 (pp (thing (bDef b)))]) where def | bInfix b = lhsOp | otherwise = lhs f = bName b sig = case bSignature b of- Nothing -> empty- Just s -> pp (DSignature [f] s)+ Nothing -> []+ Just s -> [pp (DSignature [f] s)] eq = if bMono b then text ":=" else text "="- lhs = ppL f <+> fsep (map (ppPrec 3) (bParams b))+ lhs = fsep (ppL f : (map (ppPrec 3) (bParams b))) lhsOp = case bParams b of [x,y] -> pp x <+> ppL f <+> pp y@@ -647,13 +718,17 @@ instance PPName name => PP (TySyn name) where ppPrec _ (TySyn x _ xs t) =- text "type" <+> ppL x <+> fsep (map (ppPrec 1) xs)- <+> text "=" <+> pp t+ nest 2 $ sep $+ [ fsep $ [text "type", ppL x] ++ map (ppPrec 1) xs ++ [text "="]+ , pp t+ ] instance PPName name => PP (PropSyn name) where ppPrec _ (PropSyn x _ xs ps) =- text "constraint" <+> ppL x <+> fsep (map (ppPrec 1) xs)- <+> text "=" <+> parens (commaSep (map pp ps))+ nest 2 $ sep $+ [ fsep $ [text "constraint", ppL x] ++ map (ppPrec 1) xs ++ [text "="]+ , parens (commaSep (map pp ps))+ ] instance PP Literal where ppPrec _ lit =@@ -710,7 +785,7 @@ | otherwise = bits (Just p) (p : res) (p + 1) (num `shiftR` 1) wrap :: Int -> Int -> Doc -> Doc-wrap contextPrec myPrec doc = if myPrec < contextPrec then parens doc else doc+wrap contextPrec myPrec doc = optParens (myPrec < contextPrec) doc isEApp :: Expr n -> Maybe (Expr n, Expr n) isEApp (ELocated e _) = isEApp e@@ -749,15 +824,23 @@ ERecord fs -> braces (commaSep (map (ppNamed' "=") (displayFields fs))) EList es -> brackets (commaSep (map pp es)) EFromTo e1 e2 e3 t1 -> brackets (pp e1 <.> step <+> text ".." <+> end)- where step = maybe empty (\e -> comma <+> pp e) e2+ where step = maybe mempty (\e -> comma <+> pp e) e2 end = maybe (pp e3) (\t -> pp e3 <+> colon <+> pp t) t1+ EFromToBy isStrict e1 e2 e3 t1 -> brackets (pp e1 <+> dots <+> pp e2 <+> text "by" <+> end)+ where end = maybe (pp e3) (\t -> pp e3 <+> colon <+> pp t) t1+ dots | isStrict = text ".. <"+ | otherwise = text ".."+ EFromToDownBy isStrict e1 e2 e3 t1 -> brackets (pp e1 <+> dots <+> pp e2 <+> text "down by" <+> end)+ where end = maybe (pp e3) (\t -> pp e3 <+> colon <+> pp t) t1+ dots | isStrict = text ".. >"+ | otherwise = text ".." EFromToLessThan e1 e2 t1 -> brackets (strt <+> text ".. <" <+> end) where strt = maybe (pp e1) (\t -> pp e1 <+> colon <+> pp t) t1 end = pp e2 EInfFrom e1 e2 -> brackets (pp e1 <.> step <+> text "...")- where step = maybe empty (\e -> comma <+> pp e) e2- EComp e mss -> brackets (pp e <+> vcat (map arm mss))- where arm ms = text "|" <+> commaSep (map pp ms)+ where step = maybe mempty (\e -> comma <+> pp e) e2+ EComp e mss -> brackets (pp e <> align (vcat (map arm mss)))+ where arm ms = text " |" <+> commaSep (map pp ms) EUpd mb fs -> braces (hd <+> "|" <+> commaSep (map pp fs)) where hd = maybe "_" pp mb @@ -775,10 +858,10 @@ ETyped e t -> wrap n 0 (ppPrec 2 e <+> text ":" <+> pp t) - EWhere e ds -> wrap n 0 (pp e- $$ text "where"- $$ nest 2 (vcat (map pp ds))- $$ text "")+ EWhere e ds -> wrap n 0 $ align $ vsep+ [ pp e+ , hang "where" 2 (vcat (map pp ds))+ ] -- infix applications _ | Just ifix <- isInfix expr ->@@ -814,9 +897,9 @@ case pat of PVar x -> pp (thing x) PWild -> char '_'- PTuple ps -> parens (commaSep (map pp ps))- PRecord fs -> braces (commaSep (map (ppNamed' "=") (displayFields fs)))- PList ps -> brackets (commaSep (map pp ps))+ PTuple ps -> ppTuple (map pp ps)+ PRecord fs -> ppRecord (map (ppNamed' "=") (displayFields fs))+ PList ps -> ppList (map pp ps) PTyped p t -> wrap n 0 (ppPrec 1 p <+> text ":" <+> pp t) PSplit p1 p2 -> wrap n 1 (ppPrec 1 p1 <+> text "#" <+> ppPrec 1 p2) PLocated p _ -> ppPrec n p@@ -827,13 +910,13 @@ instance PPName name => PP (Schema name) where- ppPrec _ (Forall xs ps t _) = sep [vars <+> preds, pp t]+ ppPrec _ (Forall xs ps t _) = sep (vars ++ preds ++ [pp t]) where vars = case xs of- [] -> empty- _ -> braces (commaSep (map pp xs))+ [] -> []+ _ -> [nest 1 (braces (commaSepFill (map pp xs)))] preds = case ps of- [] -> empty- _ -> parens (commaSep (map pp ps)) <+> text "=>"+ [] -> []+ _ -> [nest 1 (parens (commaSepFill (map pp ps))) <+> text "=>"] instance PP Kind where ppPrec _ KType = text "*"@@ -915,13 +998,15 @@ instance NoPos (Program name) where noPos (Program x) = Program (noPos x) -instance NoPos (Module name) where+instance NoPos (ModuleG mname name) where noPos m = Module { mName = mName m , mInstance = mInstance m- , mImports = noPos (mImports m) , mDecls = noPos (mDecls m) } +instance NoPos (NestedModule name) where+ noPos (NestedModule m) = NestedModule (noPos m)+ instance NoPos (TopDecl name) where noPos decl = case decl of@@ -932,7 +1017,10 @@ DParameterFun d -> DParameterFun (noPos d) DParameterType d -> DParameterType (noPos d) DParameterConstraint d -> DParameterConstraint (noPos d)+ DModule d -> DModule (noPos d)+ DImport d -> DImport (noPos d) + instance NoPos (PrimType name) where noPos x = x @@ -953,6 +1041,7 @@ DPatBind x y -> DPatBind (noPos x) (noPos y) DFixity f ns -> DFixity f (noPos ns) DBind x -> DBind (noPos x)+ DRec bs -> DRec (map noPos bs) DType x -> DType (noPos x) DProp x -> DProp (noPos x) DLocated x _ -> noPos x@@ -973,6 +1062,7 @@ , bPragmas = noPos (bPragmas x) , bMono = bMono x , bDoc = bDoc x+ , bExport = bExport x } instance NoPos Pragma where@@ -1001,6 +1091,10 @@ EUpd x y -> EUpd (noPos x) (noPos y) EList x -> EList (noPos x) EFromTo x y z t -> EFromTo (noPos x) (noPos y) (noPos z) (noPos t)+ EFromToBy isStrict x y z t+ -> EFromToBy isStrict (noPos x) (noPos y) (noPos z) (noPos t)+ EFromToDownBy isStrict x y z t+ -> EFromToDownBy isStrict (noPos x) (noPos y) (noPos z) (noPos t) EFromToLessThan x y t -> EFromToLessThan (noPos x) (noPos y) (noPos t) EInfFrom x y -> EInfFrom (noPos x) (noPos y) EComp x y -> EComp (noPos x) (noPos y)
+ src/Cryptol/Parser/Layout.hs view
@@ -0,0 +1,237 @@+{-# Language BlockArguments #-}+{-# Language OverloadedStrings #-}+module Cryptol.Parser.Layout where++import Cryptol.Utils.Panic(panic)+import Cryptol.Parser.Position+import Cryptol.Parser.Token++{-++We assume the existence of an explicit EOF token at the end of the input. This token is *less* indented+than all other tokens (i.e., it is at column 0)++Explicit Layout Blocks++ * The symbols `(`, `{`, and `[` start an explicit layout block.+ * While in an explicit layout block we pass through tokens, except:+ - We may start new implicit or explicit layout blocks+ - A `,` terminates any *nested* layout blocks+ - We terminate the current layout block if we encounter the matching+ closing symbol `)`, `}`, `]`++Implicit Layout Blocks++ * The keywords `where`, `private`, and `parameter` start an implicit+ layout block.+ * The layout block starts at the column of the *following* token and we+ insert "virtual start block" between the current and the following tokens.+ * While in an implicit layout block:+ - We may start new implicit or explicit layout blocks+ - We insert a "virtual separator" before tokens starting at the same+ column as the layout block, EXCEPT:+ * we do not insert a separator if the previous token was a+ "documentation comment"+ * we do not insert a separator before the first token in the block++ - The implicit layout block is ended by:+ * a token than is less indented that the block, or+ * `)`, `}`, `]`, or + * ',' but only if there is an outer paren block+ block's column.+ - When an implicit layout block ends, we insert a "virtual end block"+ token just before the token that caused the block to end.++Examples:++f = x where x = 0x1 -- end implicit layout by layout+g = 0x3 -- (`g` is less indented than `x`)++f (x where x = 2) -- end implicit layout by `)`++[ x where x = 2, 3 ] -- end implicit layout by `,`++module A where -- two implicit layout blocks with the+private -- *same* indentation (`where` and `private`)+x = 0x2+-}+++layout :: Bool -> [Located Token] -> [Located Token]+layout isMod ts0++ -- Star an implicit layout block at the top of the module+ | let t = head ts0+ rng = srcRange t+ blockCol = max 1 (col (from rng)) -- see startImplicitBlock+ , isMod && tokenType (thing t) /= KW KW_module =+ virt rng VCurlyL : go [ Virtual blockCol ] blockCol True ts0++ | otherwise =+ go [] 0 False ts0++ where++ {- State parameters for `go`:++ stack:+ The stack of implicit and explicit blocks++ lastVirt:+ The indentation of the outer most implicit block, or 0 if none.+ This can be computed from the stack but we cache+ it here as we need to check it on each token.++ noVirtSep:+ Do not emit a virtual separator even if token matches block alignment.+ This is enabled at the beginning of a block, or after a doc string,+ or if we just emitted a separtor, but have not yet consumed the+ next token.++ tokens:+ remaining tokens to process+ -}++ go stack lastVirt noVirtSep tokens++ -- End implicit layout due to indentation. If the outermost block+ -- is a lyout block we just end it. If the outermost block is an+ -- explicit layout block we report a lexical error.+ | col curLoc < lastVirt =+ endImplictBlock++ -- End implicit layout block due to a symbol+ | Just (Virtual {}) <- curBlock, endsLayout curTokTy =+ endImplictBlock++ -- End implicit layout block due to a comma+ | Just (Virtual {}) <- curBlock+ , Sym Comma <- curTokTy+ , not (null [ () | Explicit _ <- popStack ]) =+ endImplictBlock++ -- Insert a virtual separator+ | Just (Virtual {}) <- curBlock+ , col curLoc == lastVirt && not noVirtSep =+ virt curRange VSemi : go stack lastVirt True tokens++ -- Start a new implicit layout. Advances token position.+ | startsLayout curTokTy = startImplicitBlock++ -- Start a paren block. Advances token position+ | Just close <- startsParenBlock curTokTy =+ curTok : go (Explicit close : stack) lastVirt False advanceTokens++ -- End a paren block. Advances token position+ | Just (Explicit close) <- curBlock, close == curTokTy =+ curTok : go popStack lastVirt False advanceTokens++ -- Disable virtual separator after doc string. Advances token position+ | White DocStr <- curTokTy =+ curTok : go stack lastVirt True advanceTokens++ -- Check to see if we are done. Note that if we got here, implicit layout+ -- blocks should have already been closed, as `EOF` is less indented than+ -- all other tokens+ | EOF <- curTokTy =+ [curTok]++ -- Any other token, just emit. Advances token position+ | otherwise =+ curTok : go stack lastVirt False advanceTokens++ where+ curTok : advanceTokens = tokens+ curTokTy = tokenType (thing curTok)+ curRange = srcRange curTok+ curLoc = from curRange++ (curBlock,popStack) =+ case stack of+ a : b -> (Just a,b)+ [] -> (Nothing, panic "layout" ["pop empty stack"])+++ startImplicitBlock =+ let nextRng = srcRange (head advanceTokens)+ nextLoc = from nextRng+ blockCol = max 1 (col nextLoc)+ -- the `max` ensuraes that indentation is always at least 1,+ -- in case we are starting a block at the very end of the input++ in curTok+ : virt nextRng VCurlyL+ : go (Virtual blockCol : stack) blockCol True advanceTokens+++ endImplictBlock =+ case curBlock of+ Just (Virtual {}) ->+ virt curRange VCurlyR+ : go popStack newVirt False tokens+ where newVirt = case [ n | Virtual n <- popStack ] of+ n : _ -> n+ _ -> 0++ Just (Explicit c) ->+ errTok curRange (InvalidIndentation c) : advanceTokens++ Nothing -> panic "layout" ["endImplictBlock with empty stack"]+++--------------------------------------------------------------------------------++data Block =+ Virtual Int -- ^ Virtual layout block+ | Explicit TokenT -- ^ An explicit layout block, expecting this ending token.+ deriving (Show)++-- | These tokens start an implicit layout block+startsLayout :: TokenT -> Bool+startsLayout ty =+ case ty of+ KW KW_where -> True+ KW KW_private -> True+ KW KW_parameter -> True+ _ -> False++-- | These tokens end an implicit layout block+endsLayout :: TokenT -> Bool+endsLayout ty =+ case ty of+ Sym BracketR -> True+ Sym ParenR -> True+ Sym CurlyR -> True+ _ -> False++-- | These tokens start an explicit "paren" layout block.+-- If so, the result contains the corresponding closing paren.+startsParenBlock :: TokenT -> Maybe TokenT+startsParenBlock ty =+ case ty of+ Sym BracketL -> Just (Sym BracketR)+ Sym ParenL -> Just (Sym ParenR)+ Sym CurlyL -> Just (Sym CurlyR)+ _ -> Nothing+++--------------------------------------------------------------------------------++-- | Make a virtual token of the given type+virt :: Range -> TokenV -> Located Token+virt rng x = Located { srcRange = rng { to = from rng }, thing = t }+ where+ t = Token (Virt x)+ case x of+ VCurlyL -> "beginning of layout block"+ VCurlyR -> "end of layout block"+ VSemi -> "layout block separator"++errTok :: Range -> TokenErr -> Located Token+errTok rng x = Located { srcRange = rng { to = from rng }, thing = t }+ where+ t = Token { tokenType = Err x, tokenText = "" }++++
src/Cryptol/Parser/Lexer.x view
@@ -18,10 +18,13 @@ , Located(..) , Config(..) , defaultConfig+ , dbgLex ) where import Cryptol.Parser.Position+import Cryptol.Parser.Token import Cryptol.Parser.LexerUtils+import qualified Cryptol.Parser.Layout as L import Cryptol.Parser.Unlit(unLit) import Data.Text (Text) import qualified Data.Text as Text@@ -100,6 +103,7 @@ "private" { emit $ KW KW_private } "include" { emit $ KW KW_include } "module" { emit $ KW KW_module }+"submodule" { emit $ KW KW_submodule } "newtype" { emit $ KW KW_newtype } "pragma" { emit $ KW KW_pragma } "property" { emit $ KW KW_property }@@ -112,6 +116,8 @@ "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 } "infixl" { emit $ KW KW_infixl } "infixr" { emit $ KW KW_infixr }@@ -143,6 +149,7 @@ ".." { emit $ Sym DotDot } "..." { emit $ Sym DotDotDot } "..<" { emit $ Sym DotDotLt }+"..>" { emit $ Sym DotDotGt } "|" { emit $ Sym Bar } "(" { emit $ Sym ParenL } ")" { emit $ Sym ParenR }@@ -165,6 +172,9 @@ -- < can appear in the enumeration syntax `[ x .. < y ] "<" { emit $ Sym Lt } +-- > can appear in the enumeration syntax `[ x .. > y down by n ]+">" { emit $ Sym Gt }+ -- hash is used as a kind, and as a pattern "#" { emit (Op Hash ) } @@ -194,7 +204,7 @@ -- This stream is fed to the parser. lexer :: Config -> Text -> ([Located Token], Position) lexer cfg cs = ( case cfgLayout cfg of- Layout -> layout cfg lexemes+ Layout -> L.layout (cfgModuleScope cfg) lexemes NoLayout -> lexemes , finalPos )@@ -251,6 +261,11 @@ (mtok,s') = act cfg (alexPos i) txt s (rest,pos) = run i' $! s' in (mtok ++ rest, pos)++dbgLex file =+ do txt <- readFile file+ let (ts,_) = lexer defaultConfig (Text.pack txt)+ mapM_ (print . thing) ts -- vim: ft=haskell }
src/Cryptol/Parser/LexerUtils.hs view
@@ -5,19 +5,9 @@ -- Maintainer : cryptol@galois.com -- Stability : provisional -- Portability : portable--{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE BlockArguments #-} module Cryptol.Parser.LexerUtils where -import Cryptol.Parser.Position-import Cryptol.Parser.Unlit(PreProc(None))-import Cryptol.Utils.PP-import Cryptol.Utils.Panic- import Control.Monad(guard) import Data.Char(toLower,generalCategory,isAscii,ord,isSpace, isAlphaNum,isAlpha)@@ -27,9 +17,13 @@ import qualified Data.Text.Read as T import Data.Word(Word8) -import GHC.Generics (Generic)-import Control.DeepSeq+import Cryptol.Utils.Panic+import Cryptol.Parser.Position+import Cryptol.Parser.Token+import Cryptol.Parser.Unlit(PreProc(None)) ++ data Config = Config { cfgSource :: !FilePath -- ^ File that we are working on , cfgStart :: !Position -- ^ Starting position for the parser@@ -362,209 +356,6 @@ notWhite _ = True -data Block = Virtual Int -- ^ Virtual layout block- | Explicit TokenT -- ^ An explicit layout block, expecting this ending- -- token.- deriving (Show)--isExplicit :: Block -> Bool-isExplicit Explicit{} = True-isExplicit Virtual{} = False--startsLayout :: TokenT -> Bool-startsLayout (KW KW_where) = True-startsLayout (KW KW_private) = True-startsLayout (KW KW_parameter) = True-startsLayout _ = False---- Add separators computed from layout-layout :: Config -> [Located Token] -> [Located Token]-layout cfg ts0 = loop False implicitScope [] ts0- where-- (_pos0,implicitScope) = case ts0 of- t : _ -> (from (srcRange t), cfgModuleScope cfg && tokenType (thing t) /= KW KW_module)- _ -> (start,False)--- loop :: Bool -> Bool -> [Block] -> [Located Token] -> [Located Token]- loop afterDoc startBlock stack (t : ts)- | startsLayout ty = toks ++ loop False True stack' ts-- -- We don't do layout within these delimeters- | Sym ParenL <- ty = toks ++ loop False False (Explicit (Sym ParenR) : stack') ts- | Sym CurlyL <- ty = toks ++ loop False False (Explicit (Sym CurlyR) : stack') ts- | Sym BracketL <- ty = toks ++ loop False False (Explicit (Sym BracketR) : stack') ts-- | EOF <- ty = toks- | White DocStr <- ty = toks ++ loop True False stack' ts- | otherwise = toks ++ loop False False stack' ts-- where- ty = tokenType (thing t)- pos = srcRange t-- (toks,offStack)- | afterDoc = ([t], stack)- | otherwise = offsides startToks t stack-- -- add any block start tokens, and push a level on the stack- (startToks,stack')- | startBlock && ty == EOF = ( [ virt cfg (to pos) VCurlyR- , virt cfg (to pos) VCurlyL ]- , offStack )- | startBlock = ( [ virt cfg (to pos) VCurlyL ], Virtual (col (from pos)) : offStack )- | otherwise = ( [], offStack )-- loop _ _ _ [] = panic "[Lexer] layout" ["Missing EOF token"]--- offsides :: [Located Token] -> Located Token -> [Block] -> ([Located Token], [Block])- offsides startToks t = go startToks- where- go virts stack = case stack of-- -- delimit or close a layout block- Virtual c : rest- -- commas only close to an explicit marker, so if there is none, the- -- comma doesn't close anything- | Sym Comma == ty ->- if any isExplicit rest- then go (virt cfg (to pos) VCurlyR : virts) rest- else done virts stack-- | closingToken -> go (virt cfg (to pos) VCurlyR : virts) rest- | col (from pos) == c -> done (virt cfg (to pos) VSemi : virts) stack- | col (from pos) < c -> go (virt cfg (to pos) VCurlyR : virts) rest-- -- close an explicit block- Explicit close : rest | close == ty -> done virts rest- | Sym Comma == ty -> done virts stack-- _ -> done virts stack-- ty = tokenType (thing t)- pos = srcRange t-- done ts s = (reverse (t:ts), s)-- closingToken = ty `elem` [ Sym ParenR, Sym BracketR, Sym CurlyR ]--virt :: Config -> Position -> TokenV -> Located Token-virt cfg pos x = Located { srcRange = Range- { from = pos- , to = pos- , source = cfgSource cfg- }- , thing = t }- where t = Token (Virt x) $ case x of- VCurlyL -> "beginning of layout block"- VCurlyR -> "end of layout block"- VSemi -> "layout block separator"------------------------------------------------------------------------------------data Token = Token { tokenType :: !TokenT, tokenText :: !Text }- deriving (Show, Generic, NFData)---- | Virtual tokens, inserted by layout processing.-data TokenV = VCurlyL| VCurlyR | VSemi- deriving (Eq, Show, Generic, NFData)--data TokenW = BlockComment | LineComment | Space | DocStr- deriving (Eq, Show, Generic, NFData)--data TokenKW = KW_else- | KW_extern- | KW_fin- | KW_if- | KW_private- | KW_include- | KW_inf- | KW_lg2- | KW_lengthFromThen- | KW_lengthFromThenTo- | KW_max- | KW_min- | KW_module- | KW_newtype- | KW_pragma- | KW_property- | KW_then- | KW_type- | KW_where- | KW_let- | KW_x- | KW_import- | KW_as- | KW_hiding- | KW_infixl- | KW_infixr- | KW_infix- | KW_primitive- | KW_parameter- | KW_constraint- | KW_Prop- deriving (Eq, Show, Generic, NFData)---- | The named operators are a special case for parsing types, and 'Other' is--- used for all other cases that lexed as an operator.-data TokenOp = Plus | Minus | Mul | Div | Exp | Mod- | Equal | LEQ | GEQ- | Complement | Hash | At- | Other [T.Text] T.Text- deriving (Eq, Show, Generic, NFData)--data TokenSym = Bar- | ArrL | ArrR | FatArrR- | Lambda- | EqDef- | Comma- | Semi- | Dot- | DotDot- | DotDotDot- | DotDotLt- | Colon- | BackTick- | ParenL | ParenR- | BracketL | BracketR- | CurlyL | CurlyR- | TriL | TriR- | Lt- | Underscore- deriving (Eq, Show, Generic, NFData)--data TokenErr = UnterminatedComment- | UnterminatedString- | UnterminatedChar- | InvalidString- | InvalidChar- | LexicalError- | MalformedLiteral- | MalformedSelector- deriving (Eq, Show, Generic, NFData)--data SelectorType = RecordSelectorTok Text | TupleSelectorTok Int- deriving (Eq, Show, Generic, NFData)--data TokenT = Num !Integer !Int !Int -- ^ value, base, number of digits- | Frac !Rational !Int -- ^ value, base.- | ChrLit !Char -- ^ character literal- | Ident ![T.Text] !T.Text -- ^ (qualified) identifier- | StrLit !String -- ^ string literal- | Selector !SelectorType -- ^ .hello or .123- | KW !TokenKW -- ^ keyword- | Op !TokenOp -- ^ operator- | Sym !TokenSym -- ^ symbol- | Virt !TokenV -- ^ virtual token (for layout)- | White !TokenW -- ^ white space token- | Err !TokenErr -- ^ error token- | EOF- deriving (Eq, Show, Generic, NFData)--instance PP Token where- ppPrec _ (Token _ s) = text (T.unpack s) -- | Collapse characters into a single Word8, identifying ASCII, and classes of -- unicode. This came from:
src/Cryptol/Parser/Name.hs view
@@ -78,7 +78,7 @@ i = getIdent n pfx = case getModName n of Just ns -> pp ns <.> text "::"- Nothing -> empty+ Nothing -> mempty ppInfixName n | isInfixIdent i = pfx <.> pp i@@ -87,4 +87,4 @@ i = getIdent n pfx = case getModName n of Just ns -> pp ns <.> text "::"- Nothing -> empty+ Nothing -> mempty
src/Cryptol/Parser/Names.hs view
@@ -9,15 +9,26 @@ -- This module defines the scoping rules for value- and type-level -- names in Cryptol. -module Cryptol.Parser.Names where+module Cryptol.Parser.Names+ ( tnamesNT+ , tnamesT+ , tnamesC + , namesD+ , tnamesD+ , namesB+ , namesP++ , boundNames+ , boundNamesSet+ ) where+ import Cryptol.Parser.AST import Cryptol.Utils.RecordMap import Data.Set (Set) import qualified Data.Set as Set - -- | The names defined by a newtype. tnamesNT :: Newtype name -> ([Located name], ()) tnamesNT x = ([ nName x ], ())@@ -34,6 +45,8 @@ namesD decl = case decl of DBind b -> namesB b+ DRec bs -> let (xs,ys) = unzip (map namesB bs)+ in (concat xs, Set.unions ys) -- remove binders? DPatBind p e -> (namesP p, namesE e) DSignature {} -> ([],Set.empty) DFixity{} -> ([],Set.empty)@@ -42,25 +55,10 @@ DProp {} -> ([],Set.empty) DLocated d _ -> namesD d --- | The names defined and used by a single declarations in such a way--- that they cannot be duplicated in a file. For example, it is fine--- to use @x@ on the RHS of two bindings, but not on the LHS of two--- type signatures.-allNamesD :: Ord name => Decl name -> [Located name]-allNamesD decl =- case decl of- DBind b -> fst (namesB b)- DPatBind p _ -> namesP p- DSignature ns _ -> ns- DFixity _ ns -> ns- DPragma ns _ -> ns- DType ts -> [tsName ts]- DProp ps -> [psName ps]- DLocated d _ -> allNamesD d- -- | The names defined and used by a single binding. namesB :: Ord name => Bind name -> ([Located name], Set name)-namesB b = ([bName b], boundLNames (namesPs (bParams b)) (namesDef (thing (bDef b))))+namesB b =+ ([bName b], boundLNames (namesPs (bParams b)) (namesDef (thing (bDef b)))) namesDef :: Ord name => BindDef name -> Set name@@ -84,6 +82,8 @@ in Set.unions (e : map namesUF fs) EList es -> Set.unions (map namesE es) EFromTo{} -> Set.empty+ EFromToBy{} -> Set.empty+ EFromToDownBy{} -> Set.empty EFromToLessThan{} -> Set.empty EInfFrom e e' -> Set.union (namesE e) (maybe Set.empty namesE e') EComp e arms -> let (dss,uss) = unzip (map namesArm arms)@@ -164,6 +164,7 @@ DFixity {} -> ([], Set.empty) DPragma {} -> ([], Set.empty) DBind b -> ([], tnamesB b)+ DRec bs -> ([], Set.unions (map tnamesB bs)) DPatBind _ e -> ([], tnamesE e) DLocated d _ -> tnamesD d DType (TySyn n _ ps t)@@ -204,6 +205,8 @@ `Set.union` maybe Set.empty tnamesT b `Set.union` tnamesT c `Set.union` maybe Set.empty tnamesT t+ EFromToBy _ a b c t -> Set.unions [ tnamesT a, tnamesT b, tnamesT c, maybe Set.empty tnamesT t ]+ EFromToDownBy _ a b c t -> Set.unions [ tnamesT a, tnamesT b, tnamesT c, maybe Set.empty tnamesT t ] EFromToLessThan a b t -> tnamesT a `Set.union` tnamesT b `Set.union` maybe Set.empty tnamesT t EInfFrom e e' -> Set.union (tnamesE e) (maybe Set.empty tnamesE e')
src/Cryptol/Parser/NoInclude.hs view
@@ -34,7 +34,7 @@ import Cryptol.Parser.LexerUtils (Config(..),defaultConfig) import Cryptol.Parser.ParserUtils import Cryptol.Parser.Unlit (guessPreProc)-import Cryptol.Utils.PP+import Cryptol.Utils.PP hiding ((</>)) removeIncludesModule :: (FilePath -> IO ByteString) ->@@ -160,7 +160,7 @@ return rs -- | Remove includes from a module.-noIncludeModule :: Module PName -> NoIncM (Module PName)+noIncludeModule :: ModuleG mname PName -> NoIncM (ModuleG mname PName) noIncludeModule m = update `fmap` collectErrors noIncTopDecl (mDecls m) where update tds = m { mDecls = concat tds }@@ -174,13 +174,19 @@ -- reference. noIncTopDecl :: TopDecl PName -> NoIncM [TopDecl PName] noIncTopDecl td = case td of- Decl _ -> return [td]+ Decl _ -> pure [td] DPrimType {} -> pure [td]- TDNewtype _-> return [td]- DParameterType {} -> return [td]- DParameterConstraint {} -> return [td]- DParameterFun {} -> return [td]+ TDNewtype _-> pure [td]+ DParameterType {} -> pure [td]+ DParameterConstraint {} -> pure [td]+ DParameterFun {} -> pure [td] Include lf -> resolveInclude lf+ DModule tl ->+ case tlValue tl of+ NestedModule m ->+ do m1 <- noIncludeModule m+ pure [ DModule tl { tlValue = NestedModule m1 } ]+ DImport {} -> pure [td] -- | Resolve the file referenced by a include into a list of top-level -- declarations.
src/Cryptol/Parser/NoPat.hs view
@@ -44,18 +44,23 @@ instance RemovePatterns (Expr PName) where removePatterns e = runNoPatM (noPatE e) -instance RemovePatterns (Module PName) where+instance RemovePatterns (ModuleG mname PName) where removePatterns m = runNoPatM (noPatModule m) instance RemovePatterns [Decl PName] where removePatterns ds = runNoPatM (noPatDs ds) +instance RemovePatterns (NestedModule PName) where+ removePatterns (NestedModule m) = (NestedModule m1,errs)+ where (m1,errs) = removePatterns m+ simpleBind :: Located PName -> Expr PName -> Bind PName simpleBind x e = Bind { bName = x, bParams = [] , bDef = at e (Located emptyRange (DExpr e)) , bSignature = Nothing, bPragmas = [] , bMono = True, bInfix = False, bFixity = Nothing , bDoc = Nothing+ , bExport = Public } sel :: Pattern PName -> PName -> Selector -> Bind PName@@ -154,6 +159,8 @@ EUpd mb fs -> EUpd <$> traverse noPatE mb <*> traverse noPatUF fs EList es -> EList <$> mapM noPatE es EFromTo {} -> return expr+ EFromToBy {} -> return expr+ EFromToDownBy {} -> return expr EFromToLessThan{} -> return expr EInfFrom e e' -> EInfFrom <$> noPatE e <*> traverse noPatE e' EComp e mss -> EComp <$> noPatE e <*> mapM noPatArm mss@@ -226,6 +233,7 @@ DBind b -> do b1 <- noMatchB b return [DBind b1]+ DRec {} -> panic "noMatchD" [ "DRec" ] DPatBind p e -> do (p',bs) <- noPat p let (x,ts) = splitSimpleP p'@@ -240,6 +248,7 @@ , bInfix = False , bFixity = Nothing , bDoc = Nothing+ , bExport = Public } : map DBind bs DType {} -> return [decl] DProp {} -> return [decl]@@ -323,7 +332,7 @@ noPatProg :: Program PName -> NoPatM (Program PName) noPatProg (Program topDs) = Program <$> noPatTopDs topDs -noPatModule :: Module PName -> NoPatM (Module PName)+noPatModule :: ModuleG mname PName -> NoPatM (ModuleG mname PName) noPatModule m = do ds1 <- noPatTopDs (mDecls m) return m { mDecls = ds1 }@@ -385,6 +394,13 @@ TDNewtype {} -> (d :) <$> annotTopDs ds Include {} -> (d :) <$> annotTopDs ds + DModule m ->+ case removePatterns (tlValue m) of+ (m1,errs) -> do lift (mapM_ recordError errs)+ (DModule m { tlValue = m1 } :) <$> annotTopDs ds++ DImport {} -> (d :) <$> annotTopDs ds+ [] -> return [] @@ -403,6 +419,7 @@ annotD decl = case decl of DBind b -> DBind <$> lift (annotB b)+ DRec {} -> panic "annotD" [ "DRec" ] DSignature {} -> raise () DFixity{} -> raise () DPragma {} -> raise ()@@ -524,6 +541,7 @@ DSignature ns _ -> [ (thing n, [txt]) | n <- ns ] DFixity _ ns -> [ (thing n, [txt]) | n <- ns ] DBind b -> [ (thing (bName b), [txt]) ]+ DRec {} -> panic "toDocs" [ "DRec" ] DLocated d _ -> go txt d DPatBind p _ -> [ (thing n, [txt]) | n <- namesP p ]
src/Cryptol/Parser/ParserUtils.hs view
@@ -35,10 +35,10 @@ import Cryptol.Parser.AST import Cryptol.Parser.Lexer-import Cryptol.Parser.LexerUtils(SelectorType(..))+import Cryptol.Parser.Token(SelectorType(..)) import Cryptol.Parser.Position import Cryptol.Parser.Utils (translateExprToNumT,widthIdent)-import Cryptol.Utils.Ident(packModName)+import Cryptol.Utils.Ident(packModName,packIdent,modNameChunks) import Cryptol.Utils.PP import Cryptol.Utils.Panic import Cryptol.Utils.RecordMap@@ -81,6 +81,12 @@ T.unpack (tokenText it) MalformedSelector -> "malformed selector: " ++ T.unpack (tokenText it)+ InvalidIndentation c -> "invalid indentation, unmatched " +++ case c of+ Sym CurlyR -> "{ ... } "+ Sym ParenR -> "( ... )"+ Sym BracketR -> "[ ... ]"+ _ -> show c -- basically panic ] where it = thing t @@ -111,13 +117,13 @@ | White DocStr <- tokenType tok = "Unexpected documentation (/**) comment at" <+> text path <.> char ':' <.> pp pos <.> colon $$- nest 2+ indent 2 "Documentation comments need to be followed by something to document." | otherwise = text "Parse error at" <+> text path <.> char ':' <.> pp pos <.> comma $$- nest 2 (text "unexpected:" <+> pp tok)+ indent 2 (text "unexpected:" <+> pp tok) where pos = from (srcRange ltok) tok = thing ltok@@ -126,18 +132,18 @@ text "Unexpected end of file at:" <+> text path <.> char ':' <.> pp pos -ppError (HappyErrorMsg p xs) = text "Parse error at" <+> pp p $$ nest 2 (vcat (map text xs))+ppError (HappyErrorMsg p xs) = text "Parse error at" <+> pp p $$ indent 2 (vcat (map text xs)) ppError (HappyUnexpected path ltok e) =- text "Parse error at" <+>- text path <.> char ':' <.> pp pos <.> comma $$- nest 2 unexp $$- nest 2 ("expected:" <+> text e)+ nest 2 $ vcat $+ [ text "Parse error at" <+> text path <.> char ':' <.> pp pos <.> comma ]+ ++ unexp+ ++ ["expected:" <+> text e] where (unexp,pos) = case ltok of- Nothing -> (empty,start)- Just t -> ( "unexpected:" <+> text (T.unpack (tokenText (thing t)))+ Nothing -> ( [] ,start)+ Just t -> ( ["unexpected:" <+> text (T.unpack (tokenText (thing t)))] , from (srcRange t) ) @@ -372,6 +378,43 @@ (Nothing, Nothing, Nothing) -> eFromToType r e1 e2 e3 Nothing _ -> errorMessage r ["A sequence enumeration may have at most one element type annotation."] +eFromToBy :: Range -> Expr PName -> Expr PName -> Expr PName -> Bool -> ParseM (Expr PName)+eFromToBy r e1 e2 e3 isStrictBound =+ case (asETyped e1, asETyped e2, asETyped e3) of+ (Just (e1', t), Nothing, Nothing) -> eFromToByTyped r e1' e2 e3 (Just t) isStrictBound+ (Nothing, Just (e2', t), Nothing) -> eFromToByTyped r e1 e2' e3 (Just t) isStrictBound + (Nothing, Nothing, Just (e3', t)) -> eFromToByTyped r e1 e2 e3' (Just t) isStrictBound+ (Nothing, Nothing, Nothing) -> eFromToByTyped r e1 e2 e3 Nothing isStrictBound+ _ -> errorMessage r ["A sequence enumeration may have at most one element type annotation."]++eFromToByTyped :: Range -> Expr PName -> Expr PName -> Expr PName -> Maybe (Type PName) -> Bool -> ParseM (Expr PName)+eFromToByTyped r e1 e2 e3 t isStrictBound =+ EFromToBy isStrictBound+ <$> exprToNumT r e1+ <*> exprToNumT r e2+ <*> exprToNumT r e3+ <*> pure t++eFromToDownBy ::+ Range -> Expr PName -> Expr PName -> Expr PName -> Bool -> ParseM (Expr PName)+eFromToDownBy r e1 e2 e3 isStrictBound =+ case (asETyped e1, asETyped e2, asETyped e3) of+ (Just (e1', t), Nothing, Nothing) -> eFromToDownByTyped r e1' e2 e3 (Just t) isStrictBound+ (Nothing, Just (e2', t), Nothing) -> eFromToDownByTyped r e1 e2' e3 (Just t) isStrictBound + (Nothing, Nothing, Just (e3', t)) -> eFromToDownByTyped r e1 e2 e3' (Just t) isStrictBound+ (Nothing, Nothing, Nothing) -> eFromToDownByTyped r e1 e2 e3 Nothing isStrictBound+ _ -> errorMessage r ["A sequence enumeration may have at most one element type annotation."]++eFromToDownByTyped ::+ Range -> Expr PName -> Expr PName -> Expr PName -> Maybe (Type PName) -> Bool -> ParseM (Expr PName)+eFromToDownByTyped r e1 e2 e3 t isStrictBound =+ EFromToDownBy isStrictBound+ <$> exprToNumT r e1+ <*> exprToNumT r e2+ <*> exprToNumT r e3+ <*> pure t++ asETyped :: Expr n -> Maybe (Expr n, Type n) asETyped (ELocated e _) = asETyped e asETyped (ETyped e t) = Just (e, t)@@ -433,6 +476,11 @@ , tlDoc = d , tlValue = n } +exportModule :: Maybe (Located Text) -> NestedModule PName -> TopDecl PName+exportModule mbDoc m = DModule TopLevel { tlExport = Public+ , tlDoc = mbDoc+ , tlValue = m }+ mkParFun :: Maybe (Located Text) -> Located PName -> Schema PName ->@@ -464,7 +512,9 @@ 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 {}) =@@ -534,6 +584,7 @@ , bInfix = False , bFixity = Nothing , bDoc = Nothing+ , bExport = Public } -- NOTE: The lists of patterns are reversed!@@ -549,6 +600,7 @@ , bInfix = False , bFixity = Nothing , bDoc = Nothing+ , bExport = Public } where rhs :: Expr PName@@ -588,6 +640,7 @@ , bInfix = isInfixIdent (getIdent (thing ln)) , bFixity = Nothing , bDoc = Nothing+ , bExport = Public } , exportDecl Nothing Public $ DSignature [ln] sig@@ -737,18 +790,24 @@ err = errorMessage r ["Invalid constraint"] -- | Make an ordinary module-mkModule :: Located ModName ->- ([Located Import], [TopDecl PName]) ->- Module PName-mkModule nm (is,ds) = Module { mName = nm- , mInstance = Nothing- , mImports = is- , mDecls = ds- }+mkModule :: Located ModName -> [TopDecl PName] -> Module PName+mkModule nm ds = Module { mName = nm+ , mInstance = Nothing+ , mDecls = ds+ } +mkNested :: Module PName -> ParseM (NestedModule PName)+mkNested m =+ case modNameChunks (thing nm) of+ [c] -> pure (NestedModule m { mName = nm { thing = mkUnqual (packIdent c)}})+ _ -> errorMessage r+ ["Nested modules names should be a simple identifier."]+ where+ nm = mName m+ r = srcRange nm+ -- | Make an unnamed module---gets the name @Main@.-mkAnonymousModule :: ([Located Import], [TopDecl PName]) ->- Module PName+mkAnonymousModule :: [TopDecl PName] -> Module PName mkAnonymousModule = mkModule Located { srcRange = emptyRange , thing = mkModName [T.pack "Main"] }@@ -756,12 +815,11 @@ -- | Make a module which defines a functor instance. mkModuleInstance :: Located ModName -> Located ModName ->- ([Located Import], [TopDecl PName]) ->+ [TopDecl PName] -> Module PName-mkModuleInstance nm fun (is,ds) =+mkModuleInstance nm fun ds = Module { mName = nm , mInstance = Just fun- , mImports = is , mDecls = ds }
src/Cryptol/Parser/Position.hs view
@@ -10,6 +10,9 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE RecordWildCards #-} module Cryptol.Parser.Position where @@ -22,7 +25,8 @@ import Cryptol.Utils.PP data Located a = Located { srcRange :: !Range, thing :: !a }- deriving (Eq, Ord, Show, Generic, NFData)+ deriving (Eq, Ord, Show, Generic, NFData+ , Functor, Foldable, Traversable ) data Position = Position { line :: !Int, col :: !Int }@@ -65,8 +69,6 @@ rCombs :: [Range] -> Range rCombs = foldl1 rComb -instance Functor Located where- fmap f l = l { thing = f (thing l) } --------------------------------------------------------------------------------
src/Cryptol/Parser/Selector.hs view
@@ -48,16 +48,16 @@ instance PP Selector where ppPrec _ sel = case sel of- TupleSel x sig -> int x <+> ppSig tupleSig sig- RecordSel x sig -> pp x <+> ppSig recordSig sig- ListSel x sig -> int x <+> ppSig listSig sig+ TupleSel x sig -> sep (int x : ppSig tupleSig sig)+ RecordSel x sig -> sep (pp x : ppSig recordSig sig)+ ListSel x sig -> sep (int x : ppSig listSig sig) where tupleSig n = int n- recordSig xs = braces $ fsep $ punctuate comma $ map pp xs+ recordSig xs = ppRecord $ map pp xs listSig n = int n - ppSig f = maybe empty (\x -> text "/* of" <+> f x <+> text "*/")+ ppSig f = maybe [] (\x -> [text "/* of" <+> f x <+> text "*/"]) -- | Display the thing selected by the selector, nicely.
+ src/Cryptol/Parser/Token.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+module Cryptol.Parser.Token where++import Data.Text(Text)+import qualified Data.Text as Text+import Control.DeepSeq+import GHC.Generics++import Cryptol.Utils.PP++data Token = Token { tokenType :: !TokenT, tokenText :: !Text }+ deriving (Show, Generic, NFData)++-- | Virtual tokens, inserted by layout processing.+data TokenV = VCurlyL| VCurlyR | VSemi+ deriving (Eq, Show, Generic, NFData)++data TokenW = BlockComment | LineComment | Space | DocStr+ deriving (Eq, Show, Generic, NFData)++data TokenKW = KW_else+ | KW_extern+ | KW_fin+ | KW_if+ | KW_private+ | KW_include+ | KW_inf+ | KW_lg2+ | KW_lengthFromThen+ | KW_lengthFromThenTo+ | KW_max+ | KW_min+ | KW_module+ | KW_submodule+ | KW_newtype+ | KW_pragma+ | KW_property+ | KW_then+ | KW_type+ | KW_where+ | KW_let+ | KW_x+ | KW_import+ | KW_as+ | KW_hiding+ | KW_infixl+ | KW_infixr+ | KW_infix+ | KW_primitive+ | KW_parameter+ | KW_constraint+ | KW_Prop+ | KW_by+ | KW_down+ deriving (Eq, Show, Generic, NFData)++-- | The named operators are a special case for parsing types, and 'Other' is+-- used for all other cases that lexed as an operator.+data TokenOp = Plus | Minus | Mul | Div | Exp | Mod+ | Equal | LEQ | GEQ+ | Complement | Hash | At+ | Other [Text] Text+ deriving (Eq, Show, Generic, NFData)++data TokenSym = Bar+ | ArrL | ArrR | FatArrR+ | Lambda+ | EqDef+ | Comma+ | Semi+ | Dot+ | DotDot+ | DotDotDot+ | DotDotLt+ | DotDotGt+ | Colon+ | BackTick+ | ParenL | ParenR+ | BracketL | BracketR+ | CurlyL | CurlyR+ | TriL | TriR+ | Lt | Gt+ | Underscore+ deriving (Eq, Show, Generic, NFData)++data TokenErr = UnterminatedComment+ | UnterminatedString+ | UnterminatedChar+ | InvalidString+ | InvalidChar+ | LexicalError+ | MalformedLiteral+ | MalformedSelector+ | InvalidIndentation TokenT -- expected closing paren+ deriving (Eq, Show, Generic, NFData)++data SelectorType = RecordSelectorTok Text | TupleSelectorTok Int+ deriving (Eq, Show, Generic, NFData)++data TokenT = Num !Integer !Int !Int -- ^ value, base, number of digits+ | Frac !Rational !Int -- ^ value, base.+ | ChrLit !Char -- ^ character literal+ | Ident ![Text] !Text -- ^ (qualified) identifier+ | StrLit !String -- ^ string literal+ | Selector !SelectorType -- ^ .hello or .123+ | KW !TokenKW -- ^ keyword+ | Op !TokenOp -- ^ operator+ | Sym !TokenSym -- ^ symbol+ | Virt !TokenV -- ^ virtual token (for layout)+ | White !TokenW -- ^ white space token+ | Err !TokenErr -- ^ error token+ | EOF+ deriving (Eq, Show, Generic, NFData)++instance PP Token where+ ppPrec _ (Token _ s) = text (Text.unpack s)++
+ src/Cryptol/REPL/Browse.hs view
@@ -0,0 +1,155 @@+{-# Language OverloadedStrings, BlockArguments #-}+module Cryptol.REPL.Browse (BrowseHow(..), browseModContext) where++import qualified Data.Set as Set+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe(mapMaybe)+import Data.List(sortBy)+import Data.Void (Void)+import qualified Prettyprinter as PP++import Cryptol.Parser.AST(Pragma(..))+import qualified Cryptol.TypeCheck.Type as T++import Cryptol.Utils.PP+import Cryptol.ModuleSystem.Env(ModContext(..))+import Cryptol.ModuleSystem.NamingEnv(namingEnvNames)+import Cryptol.ModuleSystem.Name+import Cryptol.ModuleSystem.Interface++data BrowseHow = BrowseExported | BrowseInScope++browseModContext :: BrowseHow -> ModContext -> PP.Doc Void+browseModContext how mc = runDoc (env disp) (vcat sections)+ where+ sections = concat+ [ browseMParams (env disp) (mctxParams mc)+ , browseMods disp decls+ , browseTSyns disp decls+ , browsePrimTys disp decls+ , browseNewtypes disp decls+ , browseVars disp decls+ ]++ disp = DispInfo { dispHow = how, env = mctxNameDisp mc }+ decls = filterIfaceDecls (`Set.member` visNames) (mctxDecls mc)+ allNames = namingEnvNames (mctxNames mc)+ visNames = case how of+ BrowseInScope -> allNames+ BrowseExported -> mctxExported mc++data DispInfo = DispInfo { dispHow :: BrowseHow, env :: NameDisp }++--------------------------------------------------------------------------------+++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)))+ 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)+ 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+++++browseTSyns :: DispInfo -> IfaceDecls -> [Doc]+browseTSyns disp decls =+ ppSection disp "Type Synonyms" pp tss+ ++ ppSection disp "Constraint Synonyms" pp cts+ where+ (cts,tss) = Map.partition isCtrait (ifTySyns decls)+ isCtrait t = T.kindResult (T.kindOf (T.tsDef t)) == T.KProp++browsePrimTys :: DispInfo -> IfaceDecls -> [Doc]+browsePrimTys disp decls =+ ppSection disp "Primitive Types" ppA (ifAbstractTypes decls)+ where+ ppA a = nest 2 (sep [pp (T.atName a) <+> ":", pp (T.atKind a)])++browseNewtypes :: DispInfo -> IfaceDecls -> [Doc]+browseNewtypes disp decls =+ ppSection disp "Newtypes" T.ppNewtypeShort (ifNewtypes decls)++browseVars :: DispInfo -> IfaceDecls -> [Doc]+browseVars disp decls =+ ppSection disp "Properties" ppVar props+ ++ ppSection disp "Symbols" ppVar syms+ where+ isProp p = PragmaProperty `elem` ifDeclPragmas p+ (props,syms) = Map.partition isProp (ifDecls decls)++ ppVar d = nest 2 (sep [pp (ifDeclName d) <+> ":", pp (ifDeclSig d)])++--------------------------------------------------------------------------------++ppSection :: DispInfo -> String -> (a -> Doc) -> Map Name a -> [Doc]+ppSection disp heading ppThing mp =+ ppSectionHeading heading + case dispHow disp of+ BrowseExported | [(_,xs)] <- grouped -> ppThings xs+ _ -> concatMap ppMod grouped+ where+ grouped = groupDecls (env disp) mp++ ppThings xs = map ppThing xs ++ [" "]++ ppMod (nm,things) =+ [ "From" <+> pp nm+ , "-----" <.> text (map (const '-') (show (runDoc (env disp) (pp nm))))+ , " "+ , indent 2 (vcat (ppThings things))+ ]++ppSectionHeading :: String -> [Doc] -> [Doc]+ppSectionHeading heading body+ | null body = []+ | otherwise = + [ text heading+ , text (map (const '=') heading)+ , " "+ , indent 2 (vcat body)+ ]+++++-- | Organize by module where defined, then sort by name.+groupDecls :: NameDisp -> Map Name a -> [(ModPath,[a])]+groupDecls disp = Map.toList+ . fmap (sortByName disp)+ . Map.fromListWith (++)+ . mapMaybe toEntry+ . Map.toList+ where+ toEntry (n,a) =+ case nameInfo n of+ Declared m _ -> Just (m,[(n,a)])+ _ -> Nothing+++sortByName :: NameDisp -> [(Name,a)] -> [a]+sortByName disp = map snd . sortBy cmpByDispName+ where+ cmpByDispName (x,_) (y,_) = cmpNameDisplay disp x y+++
src/Cryptol/REPL/Command.hs view
@@ -46,6 +46,7 @@ -- Misc utilities , handleCtrlC , sanitize+ , withRWTempFile -- To support Notebook interface (might need to refactor) , replParse@@ -55,6 +56,7 @@ import Cryptol.REPL.Monad import Cryptol.REPL.Trie+import Cryptol.REPL.Browse import qualified Cryptol.ModuleSystem as M import qualified Cryptol.ModuleSystem.Name as M@@ -64,6 +66,7 @@ import qualified Cryptol.ModuleSystem.Env as M 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@@ -81,9 +84,8 @@ import qualified Cryptol.TypeCheck.Parseable as T import qualified Cryptol.TypeCheck.Subst as T import Cryptol.TypeCheck.Solve(defaultReplExpr)-import qualified Cryptol.TypeCheck.Solver.SMT as SMT import Cryptol.TypeCheck.PP (dump,ppWithNames,emptyNameMap)-import Cryptol.Utils.PP+import Cryptol.Utils.PP hiding ((</>)) import Cryptol.Utils.Panic(panic) import Cryptol.Utils.RecordMap import qualified Cryptol.Parser.AST as P@@ -106,8 +108,7 @@ import Data.Bits (shiftL, (.&.), (.|.)) import Data.Char (isSpace,isPunctuation,isSymbol,isAlphaNum,isAscii) import Data.Function (on)-import Data.List (intercalate, nub, sortBy, groupBy,- partition, isPrefixOf,intersperse)+import Data.List (intercalate, nub, isPrefixOf,intersperse) import Data.Maybe (fromMaybe,mapMaybe,isNothing) import System.Environment (lookupEnv) import System.Exit (ExitCode(ExitSuccess))@@ -117,7 +118,6 @@ import System.Directory(getHomeDirectory,setCurrentDirectory,doesDirectoryExist ,getTemporaryDirectory,setPermissions,removeFile ,emptyPermissions,setOwnerReadable)-import Data.Map (Map) import qualified Data.Map as Map import qualified Data.Set as Set import System.IO@@ -200,8 +200,12 @@ "Check the type of an expression." "" , CommandDescr [ ":b", ":browse" ] ["[ MODULE ]"] (ModNameArg browseCmd)- "Display environment for all loaded modules, or for a specific module."- ""+ "Display information about loaded modules."+ (unlines+ [ "With no arguent, :browse shows information about the names in scope."+ , "With an argument M, shows information about the names exported from M"+ ]+ ) , CommandDescr [ ":version"] [] (NoArg versionCmd) "Display the version of this Cryptol executable" ""@@ -332,10 +336,10 @@ -- $ return $!! show $ pp $ E.WithBase ppOpts val rPutStrLn (show valDoc)- P.LetInput decl -> do+ P.LetInput ds -> do -- explicitly make this a top-level declaration, so that it will -- be generalized if mono-binds is enabled- replEvalDecl decl+ replEvalDecls ds P.EmptyInput -> -- comment or empty input does nothing pure ()@@ -344,16 +348,16 @@ printCounterexample cexTy exprDoc vs = do ppOpts <- getPPValOpts docs <- mapM (rEval . E.ppValue Concrete ppOpts) vs- rPrint $ hang exprDoc 2 (sep docs) <+>- case cexTy of- SafetyViolation -> text "~> ERROR"- PredicateFalsified -> text "= False"+ let cexRes = case cexTy of+ SafetyViolation -> [text "~> ERROR"]+ PredicateFalsified -> [text "= False"]+ rPrint $ nest 2 (sep ([exprDoc] ++ docs ++ cexRes)) printSatisfyingModel :: Doc -> [Concrete.Value] -> REPL () printSatisfyingModel exprDoc vs = do ppOpts <- getPPValOpts docs <- mapM (rEval . E.ppValue Concrete ppOpts) vs- rPrint $ hang exprDoc 2 (sep docs) <+> text ("= True")+ rPrint $ nest 2 (sep ([exprDoc] ++ docs ++ [text "= True"])) dumpTestsCmd :: FilePath -> String -> (Int,Int) -> Maybe FilePath -> REPL ()@@ -781,6 +785,9 @@ ~(EnvBool yes) <- getUser "showExamples" when yes $ forM_ vss (printSatisfyingModel exprDoc) + let numModels = length tevss+ when (numModels > 1) (rPutStrLn ("Models found: " ++ show numModels))+ case exprs of [e] -> void $ bindItVariable ty e _ -> bindItVariables ty exprs@@ -881,10 +888,10 @@ Just path -> io $ writeFile path smtlib Nothing -> rPutStr smtlib - Right w4Cfg ->+ Right _w4Cfg -> do ~(EnvBool hashConsing) <- getUser "hashConsing" ~(EnvBool warnUninterp) <- getUser "warnUninterp"- result <- liftModuleCmd $ W4.satProveOffline w4Cfg hashConsing warnUninterp cmd $ \f ->+ result <- liftModuleCmd $ W4.satProveOffline hashConsing warnUninterp cmd $ \f -> do displayMsg case mfile of Just path ->@@ -977,7 +984,8 @@ whenDebug (rPutStrLn (dump def)) fDisp <- M.mctxNameDisp <$> getFocusedEnv -- type annotation ':' has precedence 2- rPrint $ runDoc fDisp $ ppPrec 2 expr <+> text ":" <+> pp sig+ rPrint $ runDoc fDisp $ group $ hang+ (ppPrec 2 expr <+> text ":") 2 (pp sig) readFileCmd :: FilePath -> REPL () readFileCmd fp = do@@ -1156,212 +1164,18 @@ quitCmd = stop browseCmd :: String -> REPL ()-browseCmd input = do- let mnames = map (M.textToModName . T.pack) (words input)- validModNames <- (:) M.interactiveName <$> getModNames- let checkModName m =- unless (m `elem` validModNames) $- rPutStrLn ("error: " ++ show m ++ " is not a loaded module.")- mapM_ checkModName mnames-- fe <- getFocusedEnv-- let params = M.mctxParams fe- iface = M.mctxDecls fe- names = M.mctxNames fe- disp = M.mctxNameDisp fe- provV = M.mctxValueProvenance fe- provT = M.mctxTypeProvenace fe--- let f &&& g = \x -> f x && g x- isUser x = case M.nameInfo x of- M.Declared _ M.SystemName -> False- _ -> True- inSet s x = x `Set.member` s-- let (visibleTypes,visibleDecls) = M.visibleNames names-- restricted = if null mnames then const True else hasAnyModName mnames-- visibleType = isUser &&& restricted &&& inSet visibleTypes- visibleDecl = isUser &&& restricted &&& inSet visibleDecls-- browseMParams visibleType visibleDecl params disp- browseTSyns visibleType provT iface disp- browsePrimTys visibleType provT iface disp- browseNewtypes visibleType provT iface disp- browseVars visibleDecl provV iface disp---browseMParams :: (M.Name -> Bool) -> (M.Name -> Bool) ->- M.IfaceParams -> NameDisp -> REPL ()-browseMParams visT visD M.IfaceParams { .. } names =- do ppBlock names ppParamTy "Type Parameters"- (sorted visT T.mtpName ifParamTypes)- ppBlock names ppParamFu "Value Parameters"- (sorted visD T.mvpName ifParamFuns)-- where- ppParamTy T.ModTParam { .. } = hang ("type" <+> pp mtpName <+> ":")- 2 (pp mtpKind)- ppParamFu T.ModVParam { .. } = hang (pp mvpName <+> ":") 2 (pp mvpType)-- sorted vis nm mp = sortBy (M.cmpNameDisplay names `on` nm)- $ filter (vis . nm) $ Map.elems mp--type Prov = Map M.Name M.DeclProvenance--browsePrimTys :: (M.Name -> Bool) -> Prov -> M.IfaceDecls -> NameDisp -> REPL ()-browsePrimTys isVisible prov M.IfaceDecls { .. } names =- ppSection (Map.elems ifAbstractTypes)- Section { secName = "Primitive Types"- , secEntryName = T.atName- , secProvenance = prov- , secDisp = names- , secPP = ppA- , secVisible = isVisible- }- where- ppA a = pp (T.atName a) <+> ":" <+> pp (T.atKind a)---browseTSyns :: (M.Name -> Bool) -> Prov -> M.IfaceDecls -> NameDisp -> REPL ()-browseTSyns isVisible prov M.IfaceDecls { .. } names =- do ppSection tss- Section { secName = "Type Synonyms"- , secEntryName = T.tsName- , secProvenance = prov- , secDisp = names- , secVisible = isVisible- , secPP = pp- }- ppSection cts- Section { secName = "Constraint Synonyms"- , secEntryName = T.tsName- , secProvenance = prov- , secDisp = names- , secVisible = isVisible- , secPP = pp- }- where- (cts,tss) = partition isCtrait (Map.elems ifTySyns)- isCtrait t = T.kindResult (T.kindOf (T.tsDef t)) == T.KProp--browseNewtypes ::- (M.Name -> Bool) -> Prov -> M.IfaceDecls -> NameDisp -> REPL ()-browseNewtypes isVisible prov M.IfaceDecls { .. } names =- ppSection (Map.elems ifNewtypes)- Section { secName = "Newtypes"- , secEntryName = T.ntName- , secVisible = isVisible- , secProvenance = prov- , secDisp = names- , secPP = T.ppNewtypeShort- }--browseVars :: (M.Name -> Bool) -> Prov -> M.IfaceDecls -> NameDisp -> REPL ()-browseVars isVisible prov M.IfaceDecls { .. } names =- do ppSection props Section { secName = "Properties"- , secEntryName = M.ifDeclName- , secVisible = isVisible- , secProvenance = prov- , secDisp = names- , secPP = ppVar- }- ppSection syms Section { secName = "Symbols"- , secEntryName = M.ifDeclName- , secVisible = isVisible- , secProvenance = prov- , secDisp = names- , secPP = ppVar- }-- where- isProp p = T.PragmaProperty `elem` (M.ifDeclPragmas p)- (props,syms) = partition isProp (Map.elems ifDecls)-- ppVar M.IfaceDecl { .. } = hang (pp ifDeclName <+> char ':') 2 (pp ifDeclSig)----data Section a = Section- { secName :: String- , secEntryName :: a -> M.Name- , secVisible :: M.Name -> Bool- , secProvenance :: Map M.Name M.DeclProvenance- , secDisp :: NameDisp- , secPP :: a -> Doc- }--ppSection :: [a] -> Section a -> REPL ()-ppSection things s- | null grouped = pure ()+browseCmd input+ | null input =+ do fe <- getFocusedEnv+ rPrint (browseModContext BrowseInScope fe) | otherwise =- do let heading = secName s- rPutStrLn heading- rPutStrLn (map (const '=') heading)- rPutStrLn ""- mapM_ ppSub grouped-- where- ppSub (p,ts) =- do let heading = provHeading p- rPutStrLn (" " ++ heading)- rPutStrLn (" " ++ map (const '-') heading)- rPutStrLn ""- rPutStrLn $ show $ runDoc (secDisp s) $ nest 4 $ vcat $ map (secPP s) ts- rPutStrLn ""-- grouped = map rearrange $- groupBy sameProv $- sortBy cmpThings- [ (n,p,t) | t <- things,- let n = secEntryName s t,- secVisible s n,- let p = case Map.lookup n (secProvenance s) of- Just i -> i- Nothing -> panic "ppSection"- [ "Name with no provenance"- , show n ]- ]-- rearrange xs = (p, [ a | (_,_,a) <- xs ])- where (_,p,_) : _ = xs-- cmpThings (n1, p1, _) (n2, p2, _) =- case cmpProv p1 p2 of- EQ -> M.cmpNameDisplay (secDisp s) n1 n2- r -> r-- sameProv (_,p1,_) (_,p2,_) = provOrd p1 == provOrd p2-- provOrd p =- case p of- M.NameIsParameter -> Left 1 :: Either Int P.ModName- M.NameIsDynamicDecl -> Left 2- M.NameIsLocalPublic -> Left 3- M.NameIsLocalPrivate -> Left 4- M.NameIsImportedFrom x -> Right x-- cmpProv p1 p2 = compare (provOrd p1) (provOrd p2)-- provHeading p =- case p of- M.NameIsParameter -> "Parameters"- M.NameIsDynamicDecl -> "REPL"- M.NameIsLocalPublic -> "Public"- M.NameIsLocalPrivate -> "Private"- M.NameIsImportedFrom m -> "From " ++ show (pp m)----ppBlock :: NameDisp -> (a -> Doc) -> String -> [a] -> REPL ()-ppBlock names ppFun name xs = unless (null xs) $- do rPutStrLn name- rPutStrLn (replicate (length name) '=')- rPrint (runDoc names (nest 4 (vcat (map ppFun xs))))- rPutStrLn ""+ case parseModName input of+ Nothing -> rPutStrLn "Invalid module name"+ Just m ->+ do mb <- M.modContextOf m <$> getModuleEnv+ case mb of+ Nothing -> rPutStrLn ("Module " ++ show input ++ " is not loaded")+ Just fe -> rPrint (browseModContext BrowseExported fe) setOptionCmd :: String -> REPL ()@@ -1414,14 +1228,16 @@ 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 (showValHelp params env disp qname) vNames +++ map (showModHelp env disp) mNames separ = rPutStrLn " ---------" sequence_ (intersperse separ helps) - when (null (vNames ++ tNames)) $+ when (null (vNames ++ tNames ++ mNames)) $ rPrint $ "Undefined name:" <+> pp qname Nothing -> rPutStrLn ("Unable to parse name: " ++ cmd)@@ -1434,6 +1250,9 @@ 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) $@@ -1463,9 +1282,9 @@ ns = T.addTNames vs emptyNameMap rs = [ "•" <+> ppWithNames ns c | c <- cs ] rPutStrLn ""- rPrint $ runDoc nameEnv $ nest 4 $+ rPrint $ runDoc nameEnv $ indent 4 $ backticks (ppWithNames ns example) <+>- "requires:" $$ nest 2 (vcat rs)+ "requires:" $$ indent 2 (vcat rs) doShowFix (T.atFixitiy a) doShowDocString (T.atDoc a)@@ -1475,12 +1294,13 @@ 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- [] -> empty- [x] -> pp x- xs -> parens $ hsep $ punctuate comma $ map pp xs- decl = text "parameter" <+> pp name <+> text ":"- <+> pp (T.mtpKind p)- $$ ctrDoc+ [] -> []+ [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 =@@ -1510,16 +1330,15 @@ return $ do rPutStrLn "" - let property- | P.PragmaProperty `elem` ifDeclPragmas = text "property"- | otherwise = empty+ let property + | P.PragmaProperty `elem` ifDeclPragmas = [text "property"]+ | otherwise = [] rPrint $ runDoc nameEnv- $ nest 4- $ property- <+> pp qname- <+> colon- <+> pp (ifDeclSig)+ $ indent 4+ $ hsep + $ property ++ [pp qname, colon, pp (ifDeclSig)]+ doShowFix $ ifDeclFixity `mplus` (guard ifDeclInfix >> return P.defaultFixity) @@ -1534,7 +1353,7 @@ return $ do rPutStrLn "" rPrint $ runDoc nameEnv- $ nest 4+ $ indent 4 $ text "parameter" <+> pp qname <+> colon <+> pp (T.mvpType p)@@ -1591,18 +1410,11 @@ -- XXX this should probably do something a bit more specific. handleCtrlC :: a -> REPL a handleCtrlC a = do rPutStrLn "Ctrl-C"+ resetTCSolver return a - -- Utilities ------------------------------------------------------------------- -hasAnyModName :: [M.ModName] -> M.Name -> Bool-hasAnyModName mnames n =- case M.nameInfo n of- M.Declared m _ -> m `elem` mnames- M.Parameter -> False-- -- | Lift a parsing action into the REPL monad. replParse :: (String -> Either ParseError a) -> String -> REPL a replParse parse str = case parse str of@@ -1648,16 +1460,16 @@ do evo <- getEvalOptsAction env <- getModuleEnv callStacks <- getCallStacks- let cfg = M.meSolverConfig env- let minp s =+ tcSolver <- getTCSolver+ let minp = M.ModuleInput { minpCallStacks = callStacks , minpEvalOpts = evo , minpByteReader = BS.readFile , minpModuleEnv = env- , minpTCSolver = s+ , minpTCSolver = tcSolver }- moduleCmdResult =<< io (SMT.withSolver cfg (cmd . minp))+ moduleCmdResult =<< io (cmd minp) moduleCmdResult :: M.ModuleRes a -> REPL a moduleCmdResult (res,ws0) = do@@ -1714,12 +1526,13 @@ let mkTop d = P.Decl P.TopLevel { P.tlExport = P.Public , P.tlDoc = Nothing , P.tlValue = d }- (names,ds') <- liftModuleCmd (M.checkDecls (map mkTop npds))+ (names,ds',tyMap) <- liftModuleCmd (M.checkDecls (map mkTop npds)) - -- extend the naming env+ -- extend the naming env and type synonym maps denv <- getDynEnv- setDynEnv denv { M.deNames = names `M.shadowing` M.deNames denv }-+ setDynEnv denv { M.deNames = names `M.shadowing` M.deNames denv+ , M.deTySyns = tyMap <> M.deTySyns denv+ } return ds' replSpecExpr :: T.Expr -> REPL T.Expr@@ -1735,9 +1548,8 @@ do validEvalContext def validEvalContext sig - me <- getModuleEnv- let cfg = M.meSolverConfig me- mbDef <- io $ SMT.withSolver cfg (\s -> defaultReplExpr s def sig)+ s <- getTCSolver+ mbDef <- io (defaultReplExpr s def sig) (def1,ty) <- case mbDef of@@ -1834,9 +1646,9 @@ seqTy = E.TVSeq (toInteger len) ty seqExpr = T.EList exprs (E.tValTy ty) -replEvalDecl :: P.Decl P.PName -> REPL ()-replEvalDecl decl = do- dgs <- replCheckDecls [decl]+replEvalDecls :: [P.Decl P.PName] -> REPL ()+replEvalDecls ds = do+ dgs <- replCheckDecls ds validEvalContext dgs whenDebug (mapM_ (\dg -> (rPutStrLn (dump dg))) dgs) liftModuleCmd (M.evalDecls dgs)
src/Cryptol/REPL/Monad.hs view
@@ -6,6 +6,7 @@ -- Stability : provisional -- Portability : portable +{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -36,6 +37,8 @@ , getModuleEnv, setModuleEnv , getDynEnv, setDynEnv , getCallStacks+ , getTCSolver+ , resetTCSolver , uniqify, freshName , whenDebug , getEvalOptsAction@@ -65,7 +68,9 @@ , getUserShowProverStats , getUserProverValidate , parsePPFloatFormat+ , parseFieldOrder , getProverConfig+ , parseSearchPath -- ** Configurable Output , getPutStr@@ -91,6 +96,7 @@ import Cryptol.Parser.Position (emptyRange, Range(from)) import qualified Cryptol.TypeCheck.AST as T import qualified Cryptol.TypeCheck as T+import qualified Cryptol.TypeCheck.Solver.SMT as SMT import qualified Cryptol.IR.FreeVars as T import qualified Cryptol.Utils.Ident as I import Cryptol.Utils.PP@@ -103,6 +109,8 @@ import qualified Cryptol.Symbolic.SBV as SBV (proverNames, setupProver, defaultProver, SBVProverConfig) import qualified Cryptol.Symbolic.What4 as W4 (proverNames, setupProver, W4ProverConfig) ++ import Control.Monad (ap,unless,when) import Control.Monad.Base import qualified Control.Monad.Catch as Ex@@ -110,12 +118,13 @@ import Control.Monad.Trans.Control import Data.Char (isSpace, toLower) import Data.IORef- (IORef,newIORef,readIORef,modifyIORef,atomicModifyIORef)+ (IORef,newIORef,readIORef,atomicModifyIORef) import Data.List (intercalate, isPrefixOf, unfoldr, sortBy) import Data.Maybe (catMaybes) import Data.Ord (comparing) import Data.Typeable (Typeable) import System.Directory (findExecutable)+import System.FilePath (splitSearchPath, searchPathSeparator) import qualified Control.Exception as X import qualified Data.Map as Map import qualified Data.Set as Set@@ -165,12 +174,27 @@ -- This is used to change the title of terminal when loading a module. , eProverConfig :: Either SBV.SBVProverConfig W4.W4ProverConfig++ , eTCConfig :: T.SolverConfig+ -- ^ Solver configuration to be used for typechecking++ , eTCSolver :: Maybe SMT.Solver+ -- ^ Solver instance to be used for typechecking++ , eTCSolverRestarts :: !Int+ -- ^ Counts how many times we've restarted the solver.+ -- 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. } + -- | Initial, empty environment.-defaultRW :: Bool -> Bool ->Logger -> IO RW+defaultRW :: Bool -> Bool -> Logger -> IO RW defaultRW isBatch callStacks l = do env <- M.initialModuleEnv+ let searchPath = M.meSearchPath env+ let solverConfig = T.defaultSolverConfig searchPath return RW { eLoadedMod = Nothing , eEditFile = Nothing@@ -182,6 +206,9 @@ , eCallStacks = callStacks , eUpdateTitle = return () , eProverConfig = Left SBV.defaultProver+ , eTCConfig = solverConfig+ , eTCSolver = Nothing+ , eTCSolverRestarts = 0 } -- | Build up the prompt for the REPL.@@ -228,8 +255,10 @@ -- | Run a REPL action with a fresh environment. runREPL :: Bool -> Bool -> Logger -> REPL a -> IO a runREPL isBatch callStacks l m = do- ref <- newIORef =<< defaultRW isBatch callStacks l- unREPL m ref+ Ex.bracket+ (newIORef =<< defaultRW isBatch callStacks l)+ (unREPL resetTCSolver)+ (unREPL m) instance Functor REPL where {-# INLINE fmap #-}@@ -331,9 +360,9 @@ $$ text "Type:" <+> pp s TypeNotTestable t -> text "The expression is not of a testable type." $$ text "Type:" <+> pp t- EvalInParamModule xs ->- text "Expression depends on definitions from a parameterized module:"- $$ nest 2 (vcat (map pp xs))+ EvalInParamModule xs -> nest 2 $ vsep $+ [ text "Expression depends on definitions from a parameterized module:" ]+ ++ map pp xs SBVError s -> text "SBV error:" $$ text s SBVException e -> text "SBV exception:" $$ text (show e) SBVPortfolioException e -> text "SBV exception:" $$ text (show e)@@ -384,7 +413,7 @@ modifyRW f = REPL (\ ref -> atomicModifyIORef ref f) modifyRW_ :: (RW -> RW) -> REPL ()-modifyRW_ f = REPL (\ ref -> modifyIORef ref f)+modifyRW_ f = REPL (\ ref -> atomicModifyIORef ref (\x -> (f x, ()))) -- | Construct the prompt for the current environment. getPrompt :: REPL String@@ -393,25 +422,56 @@ getCallStacks :: REPL Bool getCallStacks = eCallStacks <$> getRW +-- This assumes that we are not starting solvers in parallel, otherwise+-- there are a bunch of race conditions here.+getTCSolver :: REPL SMT.Solver+getTCSolver =+ do rw <- getRW+ case eTCSolver rw of+ Just s -> return s+ Nothing ->+ do ref <- REPL (\ref -> pure ref)+ let now = eTCSolverRestarts rw + 1+ upd new = if eTCSolverRestarts new == now+ then new { eTCSolver = Nothing }+ else new+ onExit = atomicModifyIORef ref (\s -> (upd s, ()))+ s <- io (SMT.startSolver onExit (eTCConfig rw))+ modifyRW_ (\rw' -> rw'{ eTCSolver = Just s+ , eTCSolverRestarts = now })+ return s+++resetTCSolver :: REPL ()+resetTCSolver =+ do mtc <- eTCSolver <$> getRW+ case mtc of+ Nothing -> return ()+ Just s ->+ do io (SMT.stopSolver s)+ modifyRW_ (\rw -> rw{ eTCSolver = Nothing })+ -- Get the setting we should use for displaying values. getPPValOpts :: REPL PPOpts getPPValOpts =- do base <- getKnownUser "base"- ascii <- getKnownUser "ascii"- infLength <- getKnownUser "infLength"+ do base <- getKnownUser "base"+ ascii <- getKnownUser "ascii"+ infLength <- getKnownUser "infLength" - fpBase <- getKnownUser "fpBase"- fpFmtTxt <- getKnownUser "fpFormat"+ fpBase <- getKnownUser "fpBase"+ fpFmtTxt <- getKnownUser "fpFormat"+ fieldOrder <- getKnownUser "fieldOrder" let fpFmt = case parsePPFloatFormat fpFmtTxt of Just f -> f Nothing -> panic "getPPOpts" [ "Failed to parse fp-format" ] - return PPOpts { useBase = base- , useAscii = ascii- , useInfLength = infLength- , useFPBase = fpBase- , useFPFormat = fpFmt+ return PPOpts { useBase = base+ , useAscii = ascii+ , useInfLength = infLength+ , useFPBase = fpBase+ , useFPFormat = fpFmt+ , useFieldOrder = fieldOrder } getEvalOptsAction :: REPL (IO EvalOpts)@@ -451,11 +511,14 @@ setSearchPath path = do me <- getModuleEnv setModuleEnv $ me { M.meSearchPath = path }+ setUserDirect "path" (EnvString (renderSearchPath path)) prependSearchPath :: [FilePath] -> REPL () prependSearchPath path = do me <- getModuleEnv- setModuleEnv $ me { M.meSearchPath = path ++ M.meSearchPath me }+ let path' = path ++ M.meSearchPath me+ setModuleEnv $ me { M.meSearchPath = path' }+ setUserDirect "path" (EnvString (renderSearchPath path')) getProverConfig :: REPL (Either SBV.SBVProverConfig W4.W4ProverConfig) getProverConfig = eProverConfig <$> getRW@@ -492,7 +555,7 @@ badName nm bs = case M.nameInfo nm of- M.Declared m _+ M.Declared (M.TopModule m) _ -- XXX: can we focus nested modules? | M.isLoadedParamMod m (M.meLoadedModules me) -> Set.insert nm bs _ -> bs @@ -547,14 +610,14 @@ getExprNames :: REPL [String] getExprNames = do fNames <- M.mctxNames <$> getFocusedEnv- return (map (show . pp) (Map.keys (M.neExprs fNames)))+ return (map (show . pp) (Map.keys (M.namespaceMap M.NSValue fNames))) -- | Get visible type signature names. -- This is used for command line completition. getTypeNames :: REPL [String] getTypeNames = do fNames <- M.mctxNames <$> getFocusedEnv- return (map (show . pp) (Map.keys (M.neTypes fNames)))+ return (map (show . pp) (Map.keys (M.namespaceMap M.NSType fNames))) -- | Return a list of property names, sorted by position in the file. getPropertyNames :: REPL ([(M.Name,M.IfaceDecl)],NameDisp)@@ -595,7 +658,8 @@ uniqify name = case M.nameInfo name of M.Declared ns s ->- M.liftSupply (M.mkDeclared ns s (M.nameIdent name) (M.nameFixity name) (M.nameLoc name))+ M.liftSupply (M.mkDeclared (M.nameNamespace name)+ ns s (M.nameIdent name) (M.nameFixity name) (M.nameLoc name)) M.Parameter -> panic "[REPL] uniqify" ["tried to uniqify a parameter: " ++ pretty name]@@ -615,9 +679,28 @@ -- the "<interactive>" namespace. freshName :: I.Ident -> M.NameSource -> REPL M.Name freshName i sys =- M.liftSupply (M.mkDeclared I.interactiveName sys i Nothing emptyRange)+ M.liftSupply (M.mkDeclared I.NSValue mpath sys i Nothing emptyRange)+ where mpath = M.TopModule I.interactiveName +parseSearchPath :: String -> [String]+parseSearchPath path = path'+#if defined(mingw32_HOST_OS) || defined(__MINGW32__)+ -- Windows paths search from end to beginning+ where path' = reverse (splitSearchPath path)+#else+ where path' = splitSearchPath path+#endif++renderSearchPath :: [String] -> String+renderSearchPath pathSegs = path+#if defined(mingw32_HOST_OS) || defined(__MINGW32__)+ -- Windows paths search from end to beginning+ where path = intercalate [searchPathSeparator] (reverse pathSegs)+#else+ where path = intercalate [searchPathSeparator] pathSegs+#endif+ -- User Environment Interaction ------------------------------------------------ -- | User modifiable environment, for things like numeric base.@@ -710,6 +793,10 @@ Just ev -> return ev Nothing -> panic "[REPL] getUser" ["option `" ++ name ++ "` does not exist"] +setUserDirect :: String -> EnvVal -> REPL ()+setUserDirect optName val = do+ modifyRW_ (\rw -> rw { eUserEnv = Map.insert optName val (eUserEnv rw) })+ getKnownUser :: IsEnvVal a => String -> REPL a getKnownUser x = fromEnvVal <$> getUser x @@ -736,6 +823,12 @@ EnvString b -> b _ -> badIsEnv "String" +instance IsEnvVal FieldOrder where+ fromEnvVal x = case x of+ EnvString s | Just o <- parseFieldOrder s+ -> o+ _ -> badIsEnv "display` or `canonical"+ badIsEnv :: String -> a badIsEnv x = panic "fromEnvVal" [ "[REPL] Expected a `" ++ x ++ "` value." ] @@ -806,6 +899,14 @@ "Choose whether to issue a warning when uninterpreted functions are used to implement primitives in the symbolic simulator." , 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+ "The search path for finding named Cryptol modules." $+ \case EnvString path ->+ do let segs = parseSearchPath path+ me <- getModuleEnv+ setModuleEnv me { M.meSearchPath = segs }+ _ -> return ()+ , OptionDescr "monoBinds" ["mono-binds"] (EnvBool True) noCheck "Whether or not to generalize bindings in a 'where' clause." $ \case EnvBool b -> do me <- getModuleEnv@@ -815,11 +916,11 @@ , OptionDescr "tcSolver" ["tc-solver"] (EnvProg "z3" [ "-smt2", "-in" ]) noCheck -- TODO: check for the program in the path "The solver that will be used by the type checker." $- \case EnvProg prog args -> do me <- getModuleEnv- let cfg = M.meSolverConfig me- setModuleEnv me { M.meSolverConfig =- cfg { T.solverPath = prog- , T.solverArgs = args } }+ \case EnvProg prog args -> do modifyRW_ (\rw -> rw { eTCConfig = (eTCConfig rw)+ { T.solverPath = prog+ , T.solverArgs = args+ }})+ resetTCSolver _ -> return () , OptionDescr "tcDebug" ["tc-debug"] (EnvNum 0)@@ -829,9 +930,10 @@ , " * 0 no debug output" , " * 1 show type-checker debug info" , " * >1 show type-checker debug info and interactions with SMT solver"]) $- \case EnvNum n -> do me <- getModuleEnv- let cfg = M.meSolverConfig me- setModuleEnv me { M.meSolverConfig = cfg{ T.solverVerbose = n } }+ \case EnvNum n -> do changed <- modifyRW (\rw -> ( rw{ eTCConfig = (eTCConfig rw){ T.solverVerbose = n } }+ , n /= T.solverVerbose (eTCConfig rw)+ ))+ when changed resetTCSolver _ -> return () , OptionDescr "coreLint" ["core-lint"] (EnvBool False) noCheck@@ -869,6 +971,13 @@ , simpleOpt "ignoreSafety" ["ignore-safety"] (EnvBool False) noCheck "Ignore safety predicates when performing :sat or :prove checks"++ , simpleOpt "fieldOrder" ["field-order"] (EnvString "display") checkFieldOrder+ $ unlines+ [ "The order that record fields are displayed in."+ , " * display try to match the order they were written in the source code"+ , " * canonical use a predictable, canonical order"+ ] ] @@ -893,7 +1002,16 @@ EnvString s | Just _ <- parsePPFloatFormat s -> noWarns Nothing _ -> noWarns $ Just "Failed to parse `fp-format`" +parseFieldOrder :: String -> Maybe FieldOrder+parseFieldOrder "canonical" = Just CanonicalOrder+parseFieldOrder "display" = Just DisplayOrder+parseFieldOrder _ = Nothing +checkFieldOrder :: Checker+checkFieldOrder val =+ case val of+ EnvString s | Just _ <- parseFieldOrder s -> noWarns Nothing+ _ -> noWarns $ Just "Failed to parse field-order (expected one of \"canonical\" or \"display\")" -- | Check the value to the `base` option. checkBase :: Checker
src/Cryptol/Symbolic.hs view
@@ -38,6 +38,8 @@ , modelPred , varModelPred , varToExpr+ , flattenShape+ , flattenShapes ) where @@ -50,6 +52,8 @@ import Cryptol.Backend import Cryptol.Backend.FloatHelpers(bfValue)+import Cryptol.Backend.SeqMap (finiteSeqMap)+import Cryptol.Backend.WordValue (wordVal) import qualified Cryptol.Eval.Concrete as Concrete import Cryptol.Eval.Value@@ -211,24 +215,42 @@ ppVarShape _sym (VarRational _n _d) = text "<rational>" ppVarShape sym (VarWord w) = text "<word:" <> integer (wordLen sym w) <> text ">" ppVarShape sym (VarFinSeq _ xs) =- brackets (fsep (punctuate comma (map (ppVarShape sym) xs)))+ ppList (map (ppVarShape sym) xs) ppVarShape sym (VarTuple xs) =- parens (sep (punctuate comma (map (ppVarShape sym) xs)))+ ppTuple (map (ppVarShape sym) xs) ppVarShape sym (VarRecord fs) =- braces (sep (punctuate comma (map ppField (displayFields fs))))+ ppRecord (map ppField (displayFields fs)) where ppField (f,v) = pp f <+> char '=' <+> ppVarShape sym v +-- | Flatten structured shapes (like tuples and sequences), leaving only+-- a sequence of variable shapes of base type.+flattenShapes :: [VarShape sym] -> [VarShape sym] -> [VarShape sym]+flattenShapes [] tl = tl+flattenShapes (x:xs) tl = flattenShape x (flattenShapes xs tl)++flattenShape :: VarShape sym -> [VarShape sym] -> [VarShape sym]+flattenShape x tl =+ case x of+ VarBit{} -> x : tl+ VarInteger{} -> x : tl+ VarRational{} -> x : tl+ VarWord{} -> x : tl+ VarFloat{} -> x : tl+ VarFinSeq _ vs -> flattenShapes vs tl+ VarTuple vs -> flattenShapes vs tl+ VarRecord fs -> flattenShapes (recordElements fs) tl+ varShapeToValue :: Backend sym => sym -> VarShape sym -> GenValue sym varShapeToValue sym var = case var of VarBit b -> VBit b VarInteger i -> VInteger i VarRational n d -> VRational (SRational n d)- VarWord w -> VWord (wordLen sym w) (return (WordVal w))+ VarWord w -> VWord (wordLen sym w) (wordVal w) VarFloat f -> VFloat f- VarFinSeq n vs -> VSeq n (finiteSeqMap (map (pure . varShapeToValue sym) vs))+ VarFinSeq n vs -> VSeq n (finiteSeqMap sym (map (pure . varShapeToValue sym) vs)) VarTuple vs -> VTuple (map (pure . varShapeToValue sym) vs) VarRecord fs -> VRecord (fmap (pure . varShapeToValue sym) fs)
src/Cryptol/Symbolic/What4.hs view
@@ -8,8 +8,10 @@ {-# LANGUAGE BlockArguments #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE ImplicitParams #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ParallelListComp #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-}@@ -33,13 +35,14 @@ import Control.Concurrent.Async import Control.Concurrent.MVar import Control.Monad.IO.Class-import Control.Monad (when, foldM, forM_)+import Control.Monad (when, foldM, forM_, void) import qualified Control.Exception as X import System.IO (Handle) import Data.Time import Data.IORef-import Data.List (intercalate)+import Data.List (intercalate, tails, inits) import Data.List.NonEmpty (NonEmpty(..))+import Data.Proxy import qualified Data.Map as Map import Data.Set (Set) import qualified Data.Set as Set@@ -60,7 +63,9 @@ import qualified Cryptol.Eval as Eval import qualified Cryptol.Eval.Concrete as Concrete import qualified Cryptol.Eval.Value as Eval+import Cryptol.Eval.Type (TValue) import Cryptol.Eval.What4+ import Cryptol.Parser.Position (emptyRange) import Cryptol.Symbolic import Cryptol.TypeCheck.AST@@ -75,7 +80,15 @@ import qualified What4.SFloat as W4 import qualified What4.SWord as SW import What4.Solver+import qualified What4.Solver.Boolector as W4+import qualified What4.Solver.CVC4 as W4+import qualified What4.Solver.ExternalABC as W4+import qualified What4.Solver.Yices as W4+import qualified What4.Solver.Z3 as W4 import qualified What4.Solver.Adapter as W4+import qualified What4.Protocol.Online as W4+import qualified What4.Protocol.SMTLib2 as W4+import qualified What4.ProblemFeatures as W4 import qualified Data.BitVector.Sized as BV import Data.Parameterized.Nonce@@ -130,32 +143,64 @@ W4Result p x -> pure (p,x) -data AnAdapter = AnAdapter (forall st. SolverAdapter st)+data AnAdapter+ = AnAdapter (forall st. SolverAdapter st)+ | forall s. W4.OnlineSolver s =>+ AnOnlineAdapter+ String+ W4.ProblemFeatures+ [W4.ConfigDesc]+ (Proxy s) data W4ProverConfig = W4ProverConfig AnAdapter+ | W4OfflineConfig | W4Portfolio (NonEmpty AnAdapter) proverConfigs :: [(String, W4ProverConfig)] proverConfigs =- [ ("w4-cvc4" , W4ProverConfig (AnAdapter cvc4Adapter) )- , ("w4-yices" , W4ProverConfig (AnAdapter yicesAdapter) )- , ("w4-z3" , W4ProverConfig (AnAdapter z3Adapter) )- , ("w4-boolector", W4ProverConfig (AnAdapter boolectorAdapter) )- , ("w4-offline" , W4ProverConfig (AnAdapter z3Adapter) )- , ("w4-any" , allSolvers)+ [ ("w4-cvc4" , W4ProverConfig cvc4OnlineAdapter)+ , ("w4-yices" , W4ProverConfig yicesOnlineAdapter)+ , ("w4-z3" , W4ProverConfig z3OnlineAdapter)+ , ("w4-boolector" , W4ProverConfig boolectorOnlineAdapter)++ , ("w4-abc" , W4ProverConfig (AnAdapter W4.externalABCAdapter))++ , ("w4-offline" , W4OfflineConfig )+ , ("w4-any" , allSolvers) ] +z3OnlineAdapter :: AnAdapter+z3OnlineAdapter =+ AnOnlineAdapter "Z3" W4.z3Features W4.z3Options+ (Proxy :: Proxy (W4.Writer W4.Z3))++yicesOnlineAdapter :: AnAdapter+yicesOnlineAdapter =+ AnOnlineAdapter "Yices" W4.yicesDefaultFeatures W4.yicesOptions+ (Proxy :: Proxy W4.Connection)++cvc4OnlineAdapter :: AnAdapter+cvc4OnlineAdapter =+ AnOnlineAdapter "CVC4" W4.cvc4Features W4.cvc4Options+ (Proxy :: Proxy (W4.Writer W4.CVC4))++boolectorOnlineAdapter :: AnAdapter+boolectorOnlineAdapter =+ AnOnlineAdapter "Boolector" W4.boolectorFeatures W4.boolectorOptions+ (Proxy :: Proxy (W4.Writer W4.Boolector))+ allSolvers :: W4ProverConfig allSolvers = W4Portfolio- $ AnAdapter z3Adapter :|- [ AnAdapter cvc4Adapter- , AnAdapter boolectorAdapter- , AnAdapter yicesAdapter+ $ z3OnlineAdapter :|+ [ cvc4OnlineAdapter+ , boolectorOnlineAdapter+ , yicesOnlineAdapter+ , AnAdapter W4.externalABCAdapter ] defaultProver :: W4ProverConfig-defaultProver = W4ProverConfig (AnAdapter z3Adapter)+defaultProver = W4ProverConfig z3OnlineAdapter proverNames :: [String] proverNames = map fst proverConfigs@@ -178,12 +223,16 @@ let msg = "What4 found the following solvers: " ++ show (adapterNames (p:ps')) in pure (Right ([msg], W4Portfolio (p:|ps'))) + Just W4OfflineConfig -> pure (Right ([], W4OfflineConfig))+ Nothing -> pure (Left ("unknown solver name: " ++ nm)) where adapterNames [] = [] adapterNames (AnAdapter adpt : ps) = solver_adapter_name adpt : adapterNames ps+ adapterNames (AnOnlineAdapter n _ _ _ : ps) =+ n : adapterNames ps filterAdapters [] = pure [] filterAdapters (p:ps) =@@ -191,12 +240,25 @@ Just _err -> filterAdapters ps Nothing -> (p:) <$> filterAdapters ps + tryAdapter :: AnAdapter -> IO (Maybe X.SomeException)+ tryAdapter (AnAdapter adpt) = do sym <- W4.newExprBuilder W4.FloatIEEERepr CryptolState globalNonceGenerator W4.extendConfig (W4.solver_adapter_config_options adpt) (W4.getConfiguration sym) W4.smokeTest sym adpt -+ tryAdapter (AnOnlineAdapter _ fs opts (_ :: Proxy s)) = test `X.catch` (pure . Just)+ where+ test =+ do sym <- W4.newExprBuilder W4.FloatIEEERepr CryptolState globalNonceGenerator+ W4.extendConfig opts (W4.getConfiguration sym)+ (proc :: W4.SolverProcess GlobalNonceGenerator s) <- W4.startSolverProcess fs Nothing sym+ res <- W4.checkSatisfiable proc "smoke test" (W4.falsePred sym)+ case res of+ W4.Unsat () -> return ()+ _ -> fail "smoke test failed, expected UNSAT!"+ void (W4.shutdownSolverProcess proc)+ return Nothing proverError :: String -> M.ModuleCmd (Maybe String, ProverResult) proverError msg minp =@@ -211,11 +273,13 @@ case cfg of W4ProverConfig p -> setupAnAdapter p W4Portfolio ps -> mapM_ setupAnAdapter ps+ W4OfflineConfig -> return () where setupAnAdapter (AnAdapter adpt) = W4.extendConfig (W4.solver_adapter_config_options adpt) (W4.getConfiguration sym)-+ setupAnAdapter (AnOnlineAdapter _n _fs opts _p) =+ W4.extendConfig opts (W4.getConfiguration sym) what4FreshFns :: W4.IsSymExprBuilder sym => sym -> FreshVarFns (What4 sym) what4FreshFns sym =@@ -350,16 +414,13 @@ Right (ts,args,safety,query) -> case pcQueryType of ProveQuery ->- singleQuery sym solverCfg primMap logData ts args- (Just safety) query+ singleQuery sym solverCfg primMap logData ts args (Just safety) query SafetyQuery ->- singleQuery sym solverCfg primMap logData ts args- (Just safety) query+ singleQuery sym solverCfg primMap logData ts args (Just safety) query SatQuery num ->- multiSATQuery sym solverCfg primMap logData ts args- query num+ multiSATQuery sym solverCfg primMap logData ts args query num printUninterpWarn :: Logger -> Set Text -> IO () printUninterpWarn lg uninterpWarns =@@ -371,17 +432,14 @@ , " " ++ intercalate ", " (map Text.unpack xs) ] satProveOffline ::- W4ProverConfig -> Bool {- ^ hash consing -} -> Bool {- ^ warn on uninterpreted functions -} -> ProverCommand -> ((Handle -> IO ()) -> IO ()) -> M.ModuleCmd (Maybe String) -satProveOffline (W4Portfolio (p:|_)) hashConsing warnUninterp cmd outputContinuation =- satProveOffline (W4ProverConfig p) hashConsing warnUninterp cmd outputContinuation+satProveOffline hashConsing warnUninterp ProverCommand{ .. } outputContinuation = -satProveOffline (W4ProverConfig (AnAdapter adpt)) hashConsing warnUninterp ProverCommand {..} outputContinuation = protectStack onError \modIn -> M.runModuleM modIn do w4sym <- liftIO makeSym@@ -396,27 +454,26 @@ case ok of Left msg -> return (Just msg) Right (_ts,_args,_safety,query) ->- do outputContinuation- (\hdl -> solver_adapter_write_smt2 adpt w4sym hdl [query])+ do outputContinuation (\hdl -> W4.writeZ3SMT2File w4sym hdl [query]) return Nothing where makeSym =- do sym <- W4.newExprBuilder W4.FloatIEEERepr CryptolState- globalNonceGenerator- W4.extendConfig (W4.solver_adapter_config_options adpt)- (W4.getConfiguration sym)+ do sym <- W4.newExprBuilder W4.FloatIEEERepr CryptolState globalNonceGenerator+ W4.extendConfig W4.z3Options (W4.getConfiguration sym) when hashConsing (W4.startCaching sym) pure sym onError msg minp = pure (Right (Just msg, M.minpModuleEnv minp), []) +{- decSatNum :: SatNum -> SatNum decSatNum (SomeSat n) | n > 0 = SomeSat (n-1) decSatNum n = n+-} -multiSATQuery ::+multiSATQuery :: forall sym t fm. sym ~ W4.ExprBuilder t CryptolState fm => What4 sym -> W4ProverConfig ->@@ -427,58 +484,145 @@ W4.Pred sym -> 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 W4OfflineConfig _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 =- fail "What4 portfolio solver cannot be used for multi SAT queries"+ fail "What4 portfolio solver cannot be used for multi-SAT queries" -multiSATQuery sym (W4ProverConfig (AnAdapter adpt)) primMap logData ts args query satNum0 =- do pres <- W4.solver_adapter_check_sat adpt (w4 sym) logData [query] $ \res ->- case res of- W4.Unknown -> return (Left (ProverError "Solver returned UNKNOWN"))- W4.Unsat _ -> return (Left (ThmResult (map unFinType ts)))- W4.Sat (evalFn,_) ->- do xs <- mapM (varShapeToConcrete evalFn) args- let model = computeModel primMap ts xs- blockingPred <- computeBlockingPred sym args xs- return (Right (model, blockingPred))+multiSATQuery _sym (W4ProverConfig (AnAdapter adpt)) _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.") - case pres of- Left res -> pure (Just (solver_adapter_name adpt), res)- Right (mdl,block) ->- do mdls <- (mdl:) <$> computeMoreModels [block,query] (decSatNum satNum0)- return (Just (solver_adapter_name adpt), AllSatResult mdls)+multiSATQuery sym (W4ProverConfig (AnOnlineAdapter nm fs _opts (_ :: Proxy s)))+ primMap _logData ts args query satNum0 =+ X.bracket+ (W4.startSolverProcess fs Nothing (w4 sym))+ (void . W4.shutdownSolverProcess)+ (\ (proc :: W4.SolverProcess t s) ->+ do W4.assume (W4.solverConn proc) query+ res <- W4.checkAndGetModel proc "query"+ case res of+ W4.Unknown -> return (Just nm, ProverError "Solver returned UNKNOWN")+ W4.Unsat _ -> return (Just nm, ThmResult (map unFinType ts))+ W4.Sat evalFn ->+ do xs <- mapM (varShapeToConcrete evalFn) args+ let mdl = computeModel primMap ts xs+ -- NB, we flatten these shapes to make sure that we can split+ -- our search across all of the atomic variables+ let vs = flattenShapes args []+ let cs = flattenShapes xs []+ mdls <- runMultiSat satNum0 $+ do yield mdl+ computeMoreModels proc vs cs+ return (Just nm, AllSatResult mdls)) where+ -- This search procedure uses incremental solving and push/pop to split on the concrete+ -- values of variables, while also helping to prevent the accumulation of unhelpful+ -- lemmas in the solver state. This algorithm is basically taken from:+ -- http://theory.stanford.edu/%7Enikolaj/programmingz3.html#sec-blocking-evaluations+ computeMoreModels ::+ W4.SolverProcess t s ->+ [VarShape (What4 sym)] ->+ [VarShape Concrete.Concrete] ->+ MultiSat ()+ computeMoreModels proc vs cs =+ -- Enumerate all the ways to split up the current model+ forM_ (computeSplits vs cs) $ \ (prefix, vi, ci, suffix) ->+ do -- open a new solver frame+ liftIO $ W4.push proc+ -- force the selected pair to be different+ liftIO $ W4.assume (W4.solverConn proc) =<< W4.notPred (w4 sym) =<< computeModelPred sym vi ci+ -- force the prefix values to be the same+ liftIO $ forM_ prefix $ \(v,c) ->+ W4.assume (W4.solverConn proc) =<< computeModelPred sym v c+ -- under these assumptions, find all the remaining models+ findMoreModels proc (vi:suffix)+ -- pop the current assumption frame+ liftIO $ W4.pop proc - computeMoreModels _qs (SomeSat n) | n <= 0 = return [] -- should never happen...- computeMoreModels qs (SomeSat n) | n <= 1 = -- final model- W4.solver_adapter_check_sat adpt (w4 sym) logData qs $ \res ->- case res of- W4.Unknown -> return []- W4.Unsat _ -> return []- W4.Sat (evalFn,_) ->- do xs <- mapM (varShapeToConcrete evalFn) args- let model = computeModel primMap ts xs- return [model]+ findMoreModels ::+ W4.SolverProcess t s ->+ [VarShape (What4 sym)] ->+ MultiSat ()+ findMoreModels proc vs =+ -- see if our current assumptions are consistent+ do res <- liftIO (W4.checkAndGetModel proc "find model")+ case res of+ -- if the solver gets stuck, drop all the way out and stop search+ W4.Unknown -> done+ -- if our assumptions are already unsatisfiable, stop search and return+ W4.Unsat _ -> return ()+ W4.Sat evalFn ->+ -- We found a model. Record it and then use it to split the remaining+ -- search variables some more.+ do xs <- liftIO (mapM (varShapeToConcrete evalFn) args)+ yield (computeModel primMap ts xs)+ cs <- liftIO (mapM (varShapeToConcrete evalFn) vs)+ computeMoreModels proc vs cs - computeMoreModels qs satNum =- do pres <- W4.solver_adapter_check_sat adpt (w4 sym) logData qs $ \res ->- case res of- W4.Unknown -> return Nothing- W4.Unsat _ -> return Nothing- W4.Sat (evalFn,_) ->- do xs <- mapM (varShapeToConcrete evalFn) args- let model = computeModel primMap ts xs- blockingPred <- computeBlockingPred sym args xs- return (Just (model, blockingPred))+-- == Support operations for multi-SAT ==+type Models = [[(TValue, Expr, Concrete.Value)]] - case pres of- Nothing -> return []- Just (mdl, block) ->- (mdl:) <$> computeMoreModels (block:qs) (decSatNum satNum)+newtype MultiSat a =+ MultiSat { unMultiSat :: Models -> SatNum -> (a -> Models -> SatNum -> IO Models) -> IO Models } +instance Functor MultiSat where+ fmap f m = MultiSat (\ms satNum k -> unMultiSat m ms satNum (k . f))++instance Applicative MultiSat where+ pure x = MultiSat (\ms satNum k -> k x ms satNum)+ mf <*> mx = mf >>= \f -> fmap f mx++instance Monad MultiSat where+ m >>= f = MultiSat (\ms satNum k -> unMultiSat m ms satNum (\x ms' satNum' -> unMultiSat (f x) ms' satNum' k))++instance MonadIO MultiSat where+ liftIO m = MultiSat (\ms satNum k -> do x <- m; k x ms satNum)++runMultiSat :: SatNum -> MultiSat a -> IO Models+runMultiSat satNum m = reverse <$> unMultiSat m [] satNum (\_ ms _ -> return ms)++done :: MultiSat a+done = MultiSat (\ms _satNum _k -> return ms)++yield :: [(TValue, Expr, Concrete.Value)] -> MultiSat ()+yield mdl = MultiSat (\ms satNum k ->+ case satNum of+ SomeSat n+ | n > 1 -> k () (mdl:ms) (SomeSat (n-1))+ | otherwise -> return (mdl:ms)+ _ -> k () (mdl:ms) satNum)++-- Compute all the ways to split a sequences of variables+-- and concrete values for those variables. Each element+-- of the list consists of a prefix of (varaible,value)+-- pairs whose values we will fix, a single (varaible,value)+-- pair that we will force to be different, and a list of+-- additional unconstrained variables.+computeSplits ::+ [VarShape (What4 sym)] ->+ [VarShape Concrete.Concrete] ->+ [ ( [(VarShape (What4 sym), VarShape Concrete.Concrete)]+ , VarShape (What4 sym)+ , VarShape Concrete.Concrete+ , [VarShape (What4 sym)]+ )+ ]+computeSplits vs cs = reverse+ [ (prefix, v, c, tl)+ | prefix <- inits (zip vs cs)+ | v <- vs+ | c <- cs+ | tl <- tail (tails vs)+ ]+-- == END Support operations for multi-SAT ==+ singleQuery :: sym ~ W4.ExprBuilder t CryptolState fm => What4 sym ->@@ -491,6 +635,10 @@ W4.Pred sym -> IO (Maybe String, ProverResult) +singleQuery _ W4OfflineConfig _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 | p <- NE.toList ps@@ -528,16 +676,37 @@ return (Just (W4.solver_adapter_name adpt), pres) +singleQuery sym (W4ProverConfig (AnOnlineAdapter nm fs _opts (_ :: Proxy s)))+ primMap _logData ts args msafe query =+ X.bracket+ (W4.startSolverProcess fs Nothing (w4 sym))+ (void . W4.shutdownSolverProcess)+ (\ (proc :: W4.SolverProcess t s) ->+ do W4.assume (W4.solverConn proc) query+ res <- W4.checkAndGetModel proc "query"+ case res of+ W4.Unknown -> return (Just nm, ProverError "Solver returned UNKNOWN")+ W4.Unsat _ -> return (Just nm, ThmResult (map unFinType ts))+ W4.Sat evalFn ->+ do xs <- mapM (varShapeToConcrete evalFn) args+ let model = computeModel primMap ts xs+ case msafe of+ Just s ->+ do s' <- W4.groundEval evalFn s+ let cexType = if s' then PredicateFalsified else SafetyViolation+ return (Just nm, CounterExample cexType model)+ Nothing -> return (Just nm, AllSatResult [ model ])+ ) -computeBlockingPred ::++computeModelPred :: sym ~ W4.ExprBuilder t CryptolState fm => What4 sym ->- [VarShape (What4 sym)] ->- [VarShape Concrete.Concrete] ->+ VarShape (What4 sym) ->+ VarShape Concrete.Concrete -> IO (W4.Pred sym)-computeBlockingPred sym vs xs =- do res <- doW4Eval (w4 sym) (modelPred sym vs xs)- W4.notPred (w4 sym) (snd res)+computeModelPred sym v c =+ snd <$> doW4Eval (w4 sym) (varModelPred sym (v, c)) varShapeToConcrete :: W4.GroundEvalFn t ->
src/Cryptol/Testing/Random.hs view
@@ -34,16 +34,18 @@ import Data.List (unfoldr, genericTake, genericIndex, genericReplicate) import qualified Data.Sequence as Seq -import System.Random (RandomGen, split, random, randomR)+import System.Random.TF.Gen+import System.Random.TF.Instances import Cryptol.Backend (Backend(..), SRational(..)) import Cryptol.Backend.FloatHelpers (floatFromBits) import Cryptol.Backend.Monad (runEval,Eval,EvalErrorEx(..)) import Cryptol.Backend.Concrete+import Cryptol.Backend.SeqMap (indexSeqMap, finiteSeqMap)+import Cryptol.Backend.WordValue (wordVal) import Cryptol.Eval.Type (TValue(..))-import Cryptol.Eval.Value (GenValue(..),SeqMap(..), WordValue(..),- ppValue, defaultPPOpts, finiteSeqMap, fromVFun)+import Cryptol.Eval.Value (GenValue(..), ppValue, defaultPPOpts, fromVFun) import Cryptol.TypeCheck.Solver.InfNat (widthInteger) import Cryptol.Utils.Ident (Ident) import Cryptol.Utils.Panic (panic)@@ -212,7 +214,7 @@ randomWord :: (Backend sym, RandomGen g) => sym -> Integer -> Gen g sym randomWord sym w _sz g = let (val, g1) = randomR (0,2^w-1) g- in (return $ VWord w (WordVal <$> wordLit sym w val), g1)+ in (VWord w . wordVal <$> wordLit sym w val, g1) {-# INLINE randomStream #-} @@ -220,7 +222,7 @@ randomStream :: (Backend sym, RandomGen g) => Gen g sym -> Gen g sym randomStream mkElem sz g = let (g1,g2) = split g- in (pure $ VStream $ IndexSeqMap $ genericIndex (unfoldr (Just . mkElem sz) g1), g2)+ in (pure $ VStream $ indexSeqMap $ genericIndex (unfoldr (Just . mkElem sz) g1), g2) {-# INLINE randomSequence #-} @@ -232,7 +234,7 @@ let f g = let (x,g') = mkElem sz g in seq x (Just (x, g')) let xs = Seq.fromList $ genericTake w $ unfoldr f g1- let v = VSeq w $ IndexSeqMap $ \i -> Seq.index xs (fromInteger i)+ let v = VSeq w $ indexSeqMap $ \i -> Seq.index xs (fromInteger i) seq xs (pure v, g2) {-# INLINE randomTuple #-}@@ -401,11 +403,11 @@ TVArray{} -> [] TVStream{} -> [] TVSeq n TVBit ->- [ VWord n (pure (WordVal (BV n x)))+ [ VWord n (wordVal (BV n x)) | x <- [ 0 .. 2^n - 1 ] ] TVSeq n el ->- [ VSeq n (finiteSeqMap (map pure xs))+ [ VSeq n (finiteSeqMap Concrete (map pure xs)) | xs <- sequence (genericReplicate n (typeValues el)) ] TVTuple ts ->
src/Cryptol/Transform/MonoValues.hs view
@@ -79,11 +79,11 @@ module Cryptol.Transform.MonoValues (rewModule) where import Cryptol.ModuleSystem.Name- (SupplyT,liftSupply,Supply,mkDeclared,NameSource(..))+ (SupplyT,liftSupply,Supply,mkDeclared,NameSource(..),ModPath(..)) import Cryptol.Parser.Position (emptyRange) import Cryptol.TypeCheck.AST hiding (splitTApp) -- XXX: just use this one import Cryptol.TypeCheck.TypeMap-import Cryptol.Utils.Ident (ModName)+import Cryptol.Utils.Ident(Namespace(..)) import Data.List(sortBy,groupBy) import Data.Either(partitionEithers) import Data.Map (Map)@@ -132,7 +132,7 @@ -- | Note that this assumes that this pass will be run only once for each -- module, otherwise we will get name collisions. rewModule :: Supply -> Module -> (Module,Supply)-rewModule s m = runM body (mName m) s+rewModule s m = runM body (TopModule (mName m)) s where body = do ds <- mapM (rewDeclGroup emptyTM) (mDecls m) return m { mDecls = ds }@@ -140,13 +140,13 @@ -------------------------------------------------------------------------------- type M = ReaderT RO (SupplyT Id)-type RO = ModName+type RO = ModPath -- | Produce a fresh top-level name. newName :: M Name newName = do ns <- ask- liftSupply (mkDeclared ns SystemName "$mono" Nothing emptyRange)+ liftSupply (mkDeclared NSValue ns SystemName "$mono" Nothing emptyRange) newTopOrLocalName :: M Name newTopOrLocalName = newName
src/Cryptol/Transform/Specialize.hs view
@@ -242,9 +242,10 @@ freshName :: Name -> [Type] -> SpecM Name freshName n _ = case nameInfo n of- Declared ns s -> liftSupply (mkDeclared ns s ident fx loc)- Parameter -> liftSupply (mkParameter ident loc)+ Declared m s -> liftSupply (mkDeclared ns m s ident fx loc)+ Parameter -> liftSupply (mkParameter ns ident loc) where+ ns = nameNamespace n fx = nameFixity n ident = nameIdent n loc = nameLoc n
src/Cryptol/TypeCheck.hs view
@@ -15,6 +15,7 @@ , InferInput(..) , InferOutput(..) , SolverConfig(..)+ , defaultSolverConfig , NameSeeds , nameSeeds , Error(..)@@ -27,12 +28,15 @@ , ppNamedError ) where +import Data.IORef(IORef,modifyIORef')+import Data.Map(Map)+ import Cryptol.ModuleSystem.Name- (liftSupply,mkDeclared,NameSource(..))+ (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-import Cryptol.TypeCheck.Depends (FromDecl) import Cryptol.TypeCheck.Error import Cryptol.TypeCheck.Monad ( runInferM@@ -41,16 +45,20 @@ , NameSeeds , nameSeeds , lookupVar+ , newLocalScope, endLocalScope+ , newModuleScope, addParamType, addParameterConstraints+ , endModuleInstance+ , io )-import Cryptol.TypeCheck.Infer (inferModule, inferBinds, inferDs)-import Cryptol.TypeCheck.InferTypes(VarType(..), SolverConfig(..))-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)-import Cryptol.Utils.PP-import Cryptol.Utils.Panic(panic)+import Cryptol.TypeCheck.Infer (inferModule, 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(..))+import Cryptol.Utils.PP+import Cryptol.Utils.Panic(panic) @@ -59,17 +67,22 @@ -- | Check a module instantiation, assuming that the functor has already -- been checked.-tcModuleInst :: Module {- ^ functor -} ->- P.Module Name {- params -} ->+-- 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 func m inp = runInferM inp- $ do x <- inferModule m- flip (foldr withParamType) (mParamTypes x) $- withParameterConstraints (mParamConstraints x) $- do y <- checkModuleInstance func x- proveModuleTopLevel- pure y+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 tcExpr :: P.Expr Name -> InferInput -> IO (InferOutput (Expr,Schema)) tcExpr e0 inp = runInferM inp@@ -92,8 +105,9 @@ , show e' , show t ]- _ -> do fresh <- liftSupply (mkDeclared exprModName SystemName- (packIdent "(expression)") Nothing loc)+ _ -> do fresh <- liftSupply $+ mkDeclared NSValue (TopModule exprModName) SystemName+ (packIdent "(expression)") Nothing loc res <- inferBinds True False [ P.Bind { P.bName = P.Located { P.srcRange = loc, P.thing = fresh }@@ -105,6 +119,7 @@ , P.bInfix = False , P.bFixity = Nothing , P.bDoc = Nothing+ , P.bExport = Public } ] case res of@@ -119,24 +134,24 @@ : map show res ) -tcDecls :: FromDecl d => [d] -> InferInput -> IO (InferOutput [DeclGroup])-tcDecls ds inp = runInferM inp $ inferDs ds $ \dgs -> do- proveModuleTopLevel- return dgs+tcDecls :: [P.TopDecl Name] -> InferInput -> IO (InferOutput ([DeclGroup],Map Name TySyn))+tcDecls ds inp = runInferM inp $+ do newLocalScope+ checkTopDecls ds+ proveModuleTopLevel+ endLocalScope ppWarning :: (Range,Warning) -> Doc-ppWarning (r,w) = text "[warning] at" <+> pp r <.> colon $$ nest 2 (pp w)+ppWarning (r,w) = nest 2 (text "[warning] at" <+> pp r <.> colon $$ pp w) ppError :: (Range,Error) -> Doc-ppError (r,w) = text "[error] at" <+> pp r <.> colon $$ nest 2 (pp w)-+ppError (r,w) = nest 2 (text "[error] at" <+> pp r <.> colon $$ pp w) ppNamedWarning :: NameMap -> (Range,Warning) -> Doc ppNamedWarning nm (r,w) =- text "[warning] at" <+> pp r <.> colon $$ nest 2 (pp (WithNames w nm))+ nest 2 (text "[warning] at" <+> pp r <.> colon $$ pp (WithNames w nm)) ppNamedError :: NameMap -> (Range,Error) -> Doc ppNamedError nm (r,e) =- text "[error] at" <+> pp r <.> colon $$ nest 2 (pp (WithNames e nm))-+ nest 2 (text "[error] at" <+> pp r <.> colon $$ pp (WithNames e nm))
src/Cryptol/TypeCheck/AST.hs view
@@ -18,10 +18,10 @@ , Name() , TFun(..) , Selector(..)- , Import(..)+ , Import, ImportG(..) , ImportSpec(..) , ExportType(..)- , ExportSpec(..), isExportedBind, isExportedType+ , ExportSpec(..), isExportedBind, isExportedType, isExported , Pragma(..) , Fixity(..) , PrimMap(..)@@ -30,10 +30,12 @@ import Cryptol.Parser.Position(Located,Range,HasLoc(..)) import Cryptol.ModuleSystem.Name+import Cryptol.ModuleSystem.Interface import Cryptol.ModuleSystem.Exports(ExportSpec(..)- , isExportedBind, isExportedType)+ , isExportedBind, isExportedType, isExported) import Cryptol.Parser.AST ( Selector(..),Pragma(..)- , Import(..), ImportSpec(..), ExportType(..)+ , Import+ , ImportG(..), ImportSpec(..), ExportType(..) , Fixity(..)) import Cryptol.Utils.Ident (Ident,isInfixIdent,ModName,PrimIdent,prelPrim) import Cryptol.Utils.RecordMap@@ -50,58 +52,60 @@ -- | A Cryptol module.-data Module = Module { mName :: !ModName- , mExports :: ExportSpec Name- , mImports :: [Import]+data ModuleG mname =+ Module { mName :: !mname+ , mExports :: ExportSpec Name+ , mImports :: [Import] - , mTySyns :: Map Name TySyn- -- ^ This is just the type-level type synonyms- -- of a module.+ {-| 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) - , mNewtypes :: Map Name Newtype- , mPrimTypes :: Map Name AbstractType+ -- params, if functor , mParamTypes :: Map Name ModTParam , mParamConstraints :: [Located Prop] , mParamFuns :: Map Name ModVParam+++ -- Declarations, including everything from non-functor+ -- submodules+ , mTySyns :: Map Name TySyn+ , mNewtypes :: Map Name Newtype+ , mPrimTypes :: Map Name AbstractType , mDecls :: [DeclGroup]+ , mFunctors :: Map Name (ModuleG Name) } deriving (Show, Generic, NFData) +emptyModule :: mname -> ModuleG mname+emptyModule nm =+ Module+ { mName = nm+ , mExports = mempty+ , mImports = []+ , mSubModules = mempty++ , mParamTypes = mempty+ , mParamConstraints = mempty+ , mParamFuns = mempty++ , mTySyns = mempty+ , mNewtypes = mempty+ , mPrimTypes = mempty+ , mDecls = mempty+ , mFunctors = mempty+ }++type Module = ModuleG ModName+ -- | Is this a parameterized module?-isParametrizedModule :: Module -> Bool+isParametrizedModule :: ModuleG mname -> Bool isParametrizedModule m = not (null (mParamTypes m) && null (mParamConstraints m) && null (mParamFuns m)) --- | 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) -mtpParam :: ModTParam -> TParam-mtpParam mtp = TParam { tpUnique = nameUnique (mtpName mtp)- , tpKind = mtpKind mtp- , tpFlav = TPModParam (mtpName mtp)- , tpInfo = desc- }- where desc = TVarInfo { tvarDesc = TVFromModParam (mtpName mtp)- , tvarSource = nameLoc (mtpName mtp)- }---- | A value parameter of a module.-data ModVParam = ModVParam- { mvpName :: Name- , mvpType :: Schema- , mvpDoc :: Maybe Text- , mvpFixity :: Maybe Fixity- } deriving (Show,Generic,NFData)-- data Expr = EList [Expr] Type -- ^ List value (with type of elements) | ETuple [Expr] -- ^ Tuple value | ERec (RecordMap Ident Expr) -- ^ Record value@@ -207,14 +211,14 @@ EList [] t -> optParens (prec > 0) $ text "[]" <+> colon <+> ppWP prec t - EList es _ -> brackets $ sep $ punctuate comma $ map ppW es+ EList es _ -> ppList $ map ppW es - ETuple es -> parens $ sep $ punctuate comma $ map ppW es+ ETuple es -> ppTuple $ map ppW es - ERec fs -> braces $ sep $ punctuate comma+ ERec fs -> ppRecord [ pp f <+> text "=" <+> ppW e | (f,e) <- displayFields fs ] - ESel e sel -> ppWP 4 e <+> text "." <.> pp sel+ ESel e sel -> ppWP 4 e <.> text "." <.> pp sel ESet _ty e sel v -> braces (pp e <+> "|" <+> pp sel <+> "=" <+> pp v) @@ -224,7 +228,7 @@ , text "else" <+> ppW e3 ] EComp _ _ e mss -> let arm ms = text "|" <+> commaSep (map ppW ms)- in brackets $ ppW e <+> vcat (map arm mss)+ in brackets $ ppW e <+> (align (vcat (map arm mss))) EVar x -> ppPrefixName x @@ -257,28 +261,29 @@ ETApp e t -> optParens (prec > 3) $ ppWP 3 e <+> ppWP 5 t - EWhere e ds -> optParens (prec > 0)- ( ppW e $$ text "where"- $$ nest 2 (vcat (map ppW ds))- $$ text "" )+ EWhere e ds -> optParens (prec > 0) $ align $ vsep $+ [ ppW e+ , hang "where" 2 (vcat (map ppW ds))+ ] where ppW x = ppWithNames nm x ppWP x = ppWithNamesPrec nm x ppLam :: NameMap -> Int -> [TParam] -> [Prop] -> [(Name,Type)] -> Expr -> Doc-ppLam nm prec [] [] [] e = ppWithNamesPrec nm prec e+ppLam nm prec [] [] [] e = nest 2 (ppWithNamesPrec nm prec e) ppLam nm prec ts ps xs e = optParens (prec > 0) $- sep [ text "\\" <.> tsD <+> psD <+> xsD <+> text "->"- , ppWithNames ns1 e- ]+ nest 2 $ sep+ [ text "\\" <.> hsep (tsD ++ psD ++ xsD ++ [text "->"])+ , ppWithNames ns1 e+ ] where ns1 = addTNames ts nm - tsD = if null ts then empty else braces $ sep $ punctuate comma $ map ppT ts- psD = if null ps then empty else parens $ sep $ punctuate comma $ map ppP ps- xsD = if null xs then empty else sep $ map ppArg xs+ tsD = if null ts then [] else [braces $ commaSep $ map ppT ts]+ psD = if null ps then [] else [parens $ commaSep $ map ppP ps]+ xsD = if null xs then [] else [sep $ map ppArg xs] ppT = ppWithNames ns1 ppP = ppWithNames ns1@@ -355,12 +360,12 @@ instance PP (WithNames Decl) where ppPrec _ (WithNames Decl { .. } nm) =- pp dName <+> text ":" <+> ppWithNames nm dSignature $$- (if null dPragmas- then empty- else text "pragmas" <+> pp dName <+> sep (map pp dPragmas)- ) $$- pp dName <+> text "=" <+> ppWithNames nm dDefinition+ vcat $+ [ pp dName <+> text ":" <+> ppWithNames nm dSignature ]+ ++ (if null dPragmas+ then []+ else [text "pragmas" <+> pp dName <+> sep (map pp dPragmas)])+ ++ [ nest 2 (sep [pp dName <+> text "=", ppWithNames nm dDefinition]) ] instance PP (WithNames DeclDef) where ppPrec _ (WithNames DPrim _) = text "<primitive>"@@ -369,10 +374,10 @@ instance PP Decl where ppPrec = ppWithNamesPrec IntMap.empty -instance PP Module where+instance PP n => PP (ModuleG n) where ppPrec = ppWithNamesPrec IntMap.empty -instance PP (WithNames Module) where+instance PP n => PP (WithNames (ModuleG n)) where ppPrec _ (WithNames Module { .. } nm) = text "module" <+> pp mName $$ -- XXX: Print exports?
src/Cryptol/TypeCheck/CheckModuleInstance.hs view
@@ -1,3 +1,4 @@+{-# Language OverloadedStrings #-} module Cryptol.TypeCheck.CheckModuleInstance (checkModuleInstance) where import Data.Map ( Map )@@ -19,17 +20,24 @@ -- | Check that the instance provides what the functor needs. checkModuleInstance :: Module {- ^ type-checked functor -} -> Module {- ^ type-checked instance -} ->- InferM Module -- ^ Instantiated module-checkModuleInstance func inst =+ 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- (ctrs, m) <- instantiateModule func (mName inst) tMap vMap+ (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 Module { mName = mName m+ return ( ren+ , Module { mName = mName m , mExports = mExports m , mImports = mImports inst ++ mImports m -- Note that this is just here to record@@ -43,7 +51,11 @@ , 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.@@ -179,6 +191,7 @@ , 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/Depends.hs
@@ -1,214 +0,0 @@--- |--- Module : Cryptol.TypeCheck.Depends--- Copyright : (c) 2013-2016 Galois, Inc.--- License : BSD3--- Maintainer : cryptol@galois.com--- Stability : provisional--- Portability : portable--{-# LANGUAGE Safe #-}-{-# LANGUAGE FlexibleInstances #-}-module Cryptol.TypeCheck.Depends where--import Cryptol.ModuleSystem.Name (Name)-import qualified Cryptol.Parser.AST as P-import Cryptol.Parser.Position(Range, Located(..), thing)-import Cryptol.Parser.Names (namesB, tnamesT, tnamesC,- boundNamesSet, boundNames)-import Cryptol.TypeCheck.Monad( InferM, getTVars )-import Cryptol.TypeCheck.Error(Error(..))-import Cryptol.Utils.Panic(panic)-import Cryptol.Utils.RecordMap(recordElements)--import Data.List(sortBy, groupBy)-import Data.Function(on)-import Data.Maybe(mapMaybe)-import Data.Graph.SCC(stronglyConnComp)-import Data.Graph (SCC(..))-import Data.Map (Map)-import qualified Data.Map as Map-import qualified Data.Set as Set-import Data.Text (Text)-import MonadLib (ExceptionT, runExceptionT, raise)--data TyDecl =- TS (P.TySyn Name) (Maybe Text) -- ^ Type synonym- | NT (P.Newtype Name) (Maybe Text) -- ^ Newtype- | AT (P.ParameterType Name) (Maybe Text) -- ^ Parameter type- | PS (P.PropSyn Name) (Maybe Text) -- ^ Property synonym- | PT (P.PrimType Name) (Maybe Text) -- ^ A primitive/abstract typee- deriving Show--setDocString :: Maybe Text -> TyDecl -> TyDecl-setDocString x d =- case d of- TS a _ -> TS a x- PS a _ -> PS a x- NT a _ -> NT a x- AT a _ -> AT a x- PT a _ -> PT a x---- | Check for duplicate and recursive type synonyms.--- Returns the type-synonyms in dependency order.-orderTyDecls :: [TyDecl] -> InferM (Either Error [TyDecl])-orderTyDecls ts =- do vs <- getTVars- ds <- combine $ map (toMap vs) ts- let ordered = mkScc [ (t,[x],deps)- | (x,(t,deps)) <- Map.toList (Map.map thing ds) ]- runExceptionT (concat `fmap` mapM check ordered)-- where- toMap vs ty@(PT p _) =- let x = P.primTName p- (as,cs) = P.primTCts p- in ( thing x- , x { thing = (ty, Set.toList $- boundNamesSet vs $- boundNames (map P.tpName as) $- Set.unions $- map tnamesC cs- )- }- )--- toMap _ ty@(AT a _) =- let x = P.ptName a- in ( thing x, x { thing = (ty, []) } )-- toMap vs ty@(NT (P.Newtype x as fs) _) =- ( thing x- , x { thing = (ty, Set.toList $- boundNamesSet vs $- boundNames (map P.tpName as) $- Set.unions $- map (tnamesT . snd) (recordElements fs)- )- }- )-- toMap vs ty@(TS (P.TySyn x _ as t) _) =- (thing x- , x { thing = (ty, Set.toList $- boundNamesSet vs $- boundNames (map P.tpName as) $- tnamesT t- )- }- )-- toMap vs ty@(PS (P.PropSyn x _ as ps) _) =- (thing x- , x { thing = (ty, Set.toList $- boundNamesSet vs $- boundNames (map P.tpName as) $- Set.unions $- map tnamesC ps- )- }- )- getN (TS x _) = thing (P.tsName x)- getN (PS x _) = thing (P.psName x)- getN (NT x _) = thing (P.nName x)- getN (AT x _) = thing (P.ptName x)- getN (PT x _) = thing (P.primTName x)-- check :: SCC TyDecl -> ExceptionT Error InferM [TyDecl]- check (AcyclicSCC x) = return [x]-- -- We don't support any recursion, for now.- -- We could support recursion between newtypes, or newtypes and tysysn.- check (CyclicSCC xs) = raise (RecursiveTypeDecls (map getN xs))---- | Associate type signatures with bindings and order bindings by dependency.-orderBinds :: [P.Bind Name] -> [SCC (P.Bind Name)]-orderBinds bs = mkScc [ (b, map thing defs, Set.toList uses)- | b <- bs- , let (defs,uses) = namesB b- ]--class FromDecl d where- toBind :: d -> Maybe (P.Bind Name)- toParamFun :: d -> Maybe (P.ParameterFun Name)- toParamConstraints :: d -> [P.Located (P.Prop Name)]- toTyDecl :: d -> Maybe TyDecl- isTopDecl :: d -> Bool--instance FromDecl (P.TopDecl Name) where- toBind (P.Decl x) = toBind (P.tlValue x)- toBind _ = Nothing-- toParamFun (P.DParameterFun d) = Just d- toParamFun _ = Nothing-- toParamConstraints (P.DParameterConstraint xs) = xs- toParamConstraints _ = []-- toTyDecl (P.DPrimType p) = Just (PT (P.tlValue p) (thing <$> P.tlDoc p))- toTyDecl (P.DParameterType d) = Just (AT d (P.ptDoc d))- toTyDecl (P.TDNewtype d) = Just (NT (P.tlValue d) (thing <$> P.tlDoc d))- toTyDecl (P.Decl x) = setDocString (thing <$> P.tlDoc x)- <$> toTyDecl (P.tlValue x)- toTyDecl _ = Nothing-- isTopDecl _ = True--instance FromDecl (P.Decl Name) where- toBind (P.DLocated d _) = toBind d- toBind (P.DBind b) = return b- toBind _ = Nothing-- toParamFun _ = Nothing- toParamConstraints _ = []-- toTyDecl (P.DLocated d _) = toTyDecl d- toTyDecl (P.DType x) = Just (TS x Nothing)- toTyDecl (P.DProp x) = Just (PS x Nothing)- toTyDecl _ = Nothing-- isTopDecl _ = False--{- | Given a list of declarations, annoted with (i) the names that they-define, and (ii) the names that they use, we compute a list of strongly-connected components of the declarations. The SCCs are in dependency order. -}-mkScc :: [(a,[Name],[Name])] -> [SCC a]-mkScc ents = stronglyConnComp $ zipWith mkGr keys ents- where- keys = [ 0 :: Integer .. ]-- mkGr i (x,_,uses) = (x,i,mapMaybe (`Map.lookup` nodeMap) uses)-- -- Maps names to node ids.- nodeMap = Map.fromList $ concat $ zipWith mkNode keys ents- mkNode i (_,defs,_) = [ (d,i) | d <- defs ]--{- | Combine a bunch of definitions into a single map. Here we check-that each name is defined only onces. -}-combineMaps :: [Map Name (Located a)] -> InferM (Map Name (Located a))-combineMaps ms = if null bad then return (Map.unions ms)- else panic "combineMaps" $ "Multiple definitions"- : map show bad- where- bad = do m <- ms- duplicates [ a { thing = x } | (x,a) <- Map.toList m ]--{- | Combine a bunch of definitions into a single map. Here we check-that each name is defined only onces. -}-combine :: [(Name, Located a)] -> InferM (Map Name (Located a))-combine m = if null bad then return (Map.fromList m)- else panic "combine" $ "Multiple definitions"- : map show bad- where- bad = duplicates [ a { thing = x } | (x,a) <- m ]---- | Identify multiple occurances of something.-duplicates :: Ord a => [Located a] -> [(a,[Range])]-duplicates = mapMaybe multiple- . groupBy ((==) `on` thing)- . sortBy (compare `on` thing)- where- multiple xs@(x : _ : _) = Just (thing x, map srcRange xs)- multiple _ = Nothing--
src/Cryptol/TypeCheck/Error.hs view
@@ -139,6 +139,12 @@ | TypeShadowing String Name String | MissingModTParam (Located Ident) | MissingModVParam (Located Ident)++ | TemporaryError Doc+ -- ^ This is for errors that don't fit other cateogories.+ -- We should not use it much, and is generally to be used+ -- for transient errors, which are due to incomplete+ -- implementation. deriving (Show, Generic, NFData) -- | When we have multiple errors on the same location, we show only the@@ -147,6 +153,10 @@ errorImportance err = case err of BareTypeApp -> 11 -- basically a parse error+ TemporaryError {} -> 11+ -- show these as usually means the user used something that doesn't work++ KindMismatch {} -> 10 TyVarWithParams {} -> 9 TypeMismatch {} -> 8@@ -236,7 +246,9 @@ MissingModTParam {} -> err MissingModVParam {} -> err + TemporaryError {} -> err + instance FVS Error where fvs err = case err of@@ -269,6 +281,8 @@ MissingModTParam {} -> Set.empty MissingModVParam {} -> Set.empty + TemporaryError {} -> Set.empty+ instance PP Warning where ppPrec = ppWithNamesPrec IntMap.empty @@ -310,11 +324,11 @@ KindMismatch mbsrc k1 k2 -> addTVarsDescsAfter names err $ nested "Incorrect type form." $- vcat [ "Expected:" <+> cppKind k1- , "Inferred:" <+> cppKind k2- , kindMismatchHint k1 k2- , maybe empty (\src -> "When checking" <+> pp src) mbsrc- ]+ vcat $+ [ "Expected:" <+> cppKind k1+ , "Inferred:" <+> cppKind k2+ ] ++ kindMismatchHint k1 k2+ ++ maybe [] (\src -> ["When checking" <+> pp src]) mbsrc TooManyTypeParams extra k -> addTVarsDescsAfter names err $@@ -341,16 +355,16 @@ RecursiveTypeDecls ts -> addTVarsDescsAfter names err $ nested "Recursive type declarations:"- (fsep $ punctuate comma $ map nm ts)+ (commaSep $ map nm ts) TypeMismatch src t1 t2 -> addTVarsDescsAfter names err $ nested "Type mismatch:" $- vcat [ "Expected type:" <+> ppWithNames names t1- , "Inferred type:" <+> ppWithNames names t2- , mismatchHint t1 t2- , "When checking" <+> pp src- ]+ vcat $+ [ "Expected type:" <+> ppWithNames names t1+ , "Inferred type:" <+> ppWithNames names t2+ ] ++ mismatchHint t1 t2+ ++ ["When checking" <+> pp src] UnsolvableGoals gs -> explainUnsolvable names gs @@ -380,7 +394,7 @@ nested ("The type" <+> ppWithNames names t <+> "is not sufficiently polymorphic.") $ vcat [ "It cannot depend on quantified variables:" <+>- sep (punctuate comma (map (ppWithNames names) xs))+ (commaSep (map (ppWithNames names) xs)) , "When checking" <+> pp src ] @@ -412,16 +426,17 @@ $$ "See" <+> pp (srcRange x) RepeatedTypeParameter x rs ->- addTVarsDescsAfter names err $- "Multiple definitions for type parameter `" <.> pp x <.> "`:"- $$ nest 2 (bullets (map pp rs))+ addTVarsDescsAfter names err $ nest 2 $+ "Multiple definitions for type parameter `" <.> pp x <.> "`:"+ $$ bullets (map pp rs) AmbiguousSize x t -> let sizeMsg = case t of- Just t' -> "Must be at least:" <+> ppWithNames names t'- Nothing -> empty- in addTVarsDescsAfter names err ("Ambiguous numeric type:" <+> pp (tvarDesc x) $$ sizeMsg)+ Just t' -> ["Must be at least:" <+> ppWithNames names t']+ Nothing -> []+ in addTVarsDescsAfter names err+ (vcat (["Ambiguous numeric type:" <+> pp (tvarDesc x)] ++ sizeMsg)) BareTypeApp -> "Unexpected bare type application." $$@@ -436,13 +451,11 @@ MissingModVParam x -> "Missing definition for value parameter" <+> quotes (pp (thing x)) ---+ TemporaryError doc -> doc where bullets xs = vcat [ "•" <+> d | d <- xs ] - nested x y = x $$ nest 2 y+ nested x y = nest 2 (x $$ y) pl 1 x = text "1" <+> text x pl n x = text (show n) <+> text x <.> text "s"@@ -451,18 +464,18 @@ kindMismatchHint k1 k2 = case (k1,k2) of- (KType,KProp) -> "Possibly due to a missing `=>`"- _ -> empty+ (KType,KProp) -> [text "Possibly due to a missing `=>`"]+ _ -> [] mismatchHint (TRec fs1) (TRec fs2) =- hint "Missing" missing $$ hint "Unexpected" extra+ hint "Missing" missing ++ hint "Unexpected" extra where missing = displayOrder fs1 \\ displayOrder fs2 extra = displayOrder fs2 \\ displayOrder fs1- hint _ [] = mempty- hint s [x] = text s <+> text "field" <+> pp x- hint s xs = text s <+> text "fields" <+> commaSep (map pp xs)- mismatchHint _ _ = mempty+ hint _ [] = []+ hint s [x] = [text s <+> text "field" <+> pp x]+ hint s xs = [text s <+> text "fields" <+> commaSep (map pp xs)]+ mismatchHint _ _ = [] noUni = Set.null (Set.filter isFreeTV (fvs err)) @@ -478,18 +491,17 @@ explain g =- let useCtr = "Unsolvable constraint:" $$- nest 2 (ppWithNames names g)+ let useCtr = hang "Unsolvable constraint:" 2 (ppWithNames names g) in case tNoUser (goal g) of TCon (PC pc) ts -> let tys = [ backticks (ppWithNames names t) | t <- ts ] doc1 : _ = tys- custom msg = msg $$- nest 2 (text "arising from" $$- pp (goalSource g) $$- text "at" <+> pp (goalRange g))+ custom msg = hang msg+ 2 (text "arising from" $$+ pp (goalSource g) $$+ text "at" <+> pp (goalRange g)) in case pc of PEqual -> useCtr@@ -499,7 +511,7 @@ PPrime -> useCtr PHas sel ->- custom ("Type" <+> doc1 <+> "does not have field" <+> f+ custom ("Type" <+> doc1 </> "does not have field" <+> f <+> "of type" <+> (tys !! 1)) where f = case sel of P.TupleSel n _ -> int n@@ -507,39 +519,39 @@ P.ListSel n _ -> int n PZero ->- custom ("Type" <+> doc1 <+> "does not have `zero`")+ custom ("Type" <+> doc1 </> "does not have `zero`") PLogic ->- custom ("Type" <+> doc1 <+> "does not support logical operations.")+ custom ("Type" <+> doc1 </> "does not support logical operations.") PRing ->- custom ("Type" <+> doc1 <+> "does not support ring operations.")+ custom ("Type" <+> doc1 </> "does not support ring operations.") PIntegral ->- custom (doc1 <+> "is not an integral type.")+ custom (doc1 </> "is not an integral type.") PField ->- custom ("Type" <+> doc1 <+> "does not support field operations.")+ custom ("Type" <+> doc1 </> "does not support field operations.") PRound ->- custom ("Type" <+> doc1 <+> "does not support rounding operations.")+ custom ("Type" <+> doc1 </> "does not support rounding operations.") PEq ->- custom ("Type" <+> doc1 <+> "does not support equality.")+ custom ("Type" <+> doc1 </> "does not support equality.") PCmp ->- custom ("Type" <+> doc1 <+> "does not support comparisons.")+ custom ("Type" <+> doc1 </> "does not support comparisons.") PSignedCmp ->- custom ("Type" <+> doc1 <+> "does not support signed comparisons.")+ custom ("Type" <+> doc1 </> "does not support signed comparisons.") PLiteral -> let doc2 = tys !! 1- in custom (doc1 <+> "is not a valid literal of type" <+> doc2)+ in custom (doc1 </> "is not a valid literal of type" <+> doc2) PLiteralLessThan -> let doc2 = tys !! 1- in custom ("Type" <+> doc2 <+> "does not contain all literals below" <+> (doc1 <> "."))+ in custom ("Type" <+> doc2 </> "does not contain all literals below" <+> (doc1 <> ".")) PFLiteral -> case ts of@@ -547,14 +559,14 @@ let frac = backticks (ppWithNamesPrec names 4 m <> "/" <> ppWithNamesPrec names 4 n) ty = tys !! 3- in custom (frac <+> "is not a valid literal of type" <+> ty)+ in custom (frac </> "is not a valid literal of type" </> ty) PValidFloat -> case ts of- ~[e,p] ->- custom ("Unsupported floating point parameters:" $$- nest 2 ("exponent =" <+> ppWithNames names e $$- "precision =" <+> ppWithNames names p))+ ~[e,p] -> + custom (hang "Unsupported floating point parameters:"+ 2 ("exponent =" <+> ppWithNames names e $$+ "precision =" <+> ppWithNames names p)) PAnd -> useCtr
src/Cryptol/TypeCheck/Infer.hs view
@@ -13,16 +13,18 @@ {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE BlockArguments #-} {-# LANGUAGE Safe #-} module Cryptol.TypeCheck.Infer ( checkE , checkSigB , inferModule , inferBinds- , inferDs+ , checkTopDecls ) where +import Data.Text(Text) import qualified Data.Text as Text @@ -41,7 +43,6 @@ checkPrimType, checkParameterConstraints) import Cryptol.TypeCheck.Instantiate-import Cryptol.TypeCheck.Depends import Cryptol.TypeCheck.Subst (listSubst,apSubst,(@@),isEmptySubst) import Cryptol.Utils.Ident import Cryptol.Utils.Panic(panic)@@ -50,43 +51,24 @@ import qualified Data.Map as Map import Data.Map (Map) import qualified Data.Set as Set-import Data.List(foldl',sortBy)+import Data.List(foldl',sortBy,groupBy) import Data.Either(partitionEithers)-import Data.Maybe(mapMaybe,isJust, fromMaybe)+import Data.Maybe(isJust, fromMaybe, mapMaybe) import Data.List(partition)-import Data.Graph(SCC(..)) import Data.Ratio(numerator,denominator) import Data.Traversable(forM)-import Control.Monad(zipWithM,unless,foldM)+import Data.Function(on)+import Control.Monad(zipWithM,unless,foldM,forM_) inferModule :: P.Module Name -> InferM Module inferModule m =- inferDs (P.mDecls m) $ \ds1 ->- do proveModuleTopLevel- ts <- getTSyns- nts <- getNewtypes- ats <- getAbstractTypes- pTs <- getParamTypes- pCs <- getParamConstraints- pFuns <- getParamFuns- return Module { mName = thing (P.mName m)- , mExports = P.modExports m- , mImports = map thing (P.mImports m)- , mTySyns = Map.mapMaybe onlyLocal ts- , mNewtypes = Map.mapMaybe onlyLocal nts- , mPrimTypes = Map.mapMaybe onlyLocal ats- , mParamTypes = pTs- , mParamConstraints = pCs- , mParamFuns = pFuns- , mDecls = ds1- }- where- onlyLocal (IsLocal, x) = Just x- onlyLocal (IsExternal, _) = Nothing--+ do newModuleScope (thing (P.mName m)) (map thing (P.mImports m))+ (P.modExports m)+ checkTopDecls (P.mDecls m)+ proveModuleTopLevel+ endModule -- | Construct a Prelude primitive in the parsed AST. mkPrim :: String -> InferM (P.Expr Name)@@ -164,9 +146,8 @@ -- Here is an example of why this might be useful: -- f ` { x = T } where type T = ... P.EWhere e ds ->- inferDs ds $ \ds1 -> do e1 <- appTys e ts tGoal- return (EWhere e1 ds1)- -- XXX: Is there a scoping issue here? I think not, but check.+ do (e1,ds1) <- checkLocalDecls ds (appTys e ts tGoal)+ pure (EWhere e1 ds1) P.ELocated e r -> do e' <- inRange r (appTys e ts tGoal)@@ -183,6 +164,8 @@ P.ESel {} -> mono P.EList {} -> mono P.EFromTo {} -> mono+ P.EFromToBy {} -> mono+ P.EFromToDownBy {} -> mono P.EFromToLessThan {} -> mono P.EInfFrom {} -> mono P.EComp {} -> mono@@ -295,6 +278,58 @@ es' <- mapM checkElem es return (EList es' a) + P.EFromToBy isStrict t1 t2 t3 mety+ | isStrict ->+ do l <- curRange+ let fs = [("first",t1),("bound",t2),("stride",t3)] +++ case mety of+ Just ety -> [("a",ety)]+ Nothing -> []+ prim <- mkPrim "fromToByLessThan"+ let e' = P.EAppT prim+ [ P.NamedInst P.Named{ name = Located l (packIdent x), value = y }+ | (x,y) <- fs+ ]+ checkE e' tGoal+ | otherwise ->+ do l <- curRange+ let fs = [("first",t1),("last",t2),("stride",t3)] +++ case mety of+ Just ety -> [("a",ety)]+ Nothing -> []+ prim <- mkPrim "fromToBy"+ let e' = P.EAppT prim+ [ P.NamedInst P.Named{ name = Located l (packIdent x), value = y }+ | (x,y) <- fs+ ]+ checkE e' tGoal++ P.EFromToDownBy isStrict t1 t2 t3 mety+ | isStrict ->+ do l <- curRange+ let fs = [("first",t1),("bound",t2),("stride",t3)] +++ case mety of+ Just ety -> [("a",ety)]+ Nothing -> []+ prim <- mkPrim "fromToDownByGreaterThan"+ let e' = P.EAppT prim+ [ P.NamedInst P.Named{ name = Located l (packIdent x), value = y }+ | (x,y) <- fs+ ]+ checkE e' tGoal+ | otherwise ->+ do l <- curRange+ let fs = [("first",t1),("last",t2),("stride",t3)] +++ case mety of+ Just ety -> [("a",ety)]+ Nothing -> []+ prim <- mkPrim "fromToDownBy"+ let e' = P.EAppT prim+ [ P.NamedInst P.Named{ name = Located l (packIdent x), value = y }+ | (x,y) <- fs+ ]+ checkE e' tGoal+ P.EFromToLessThan t1 t2 mety -> do l <- curRange let fs0 =@@ -349,7 +384,24 @@ ds <- combineMaps dss e' <- withMonoTypes ds (checkE e (WithSource a TypeOfSeqElement)) return (EComp len a e' mss')+ where+ -- the renamer should have made these checks already?+ combineMaps ms = if null bad+ then return (Map.unions ms)+ else panic "combineMaps" $ "Multiple definitions"+ : map show bad+ where+ bad = do m <- ms+ duplicates [ a { thing = x } | (x,a) <- Map.toList m ]+ duplicates = mapMaybe multiple+ . groupBy ((==) `on` thing)+ . sortBy (compare `on` thing)+ where+ multiple xs@(x : _ : _) = Just (thing x, map srcRange xs)+ multiple _ = Nothing ++ P.EAppT e fs -> appTys e (map uncheckedTypeArg fs) tGoal P.EApp e1 e2 ->@@ -366,8 +418,8 @@ return (EIf e1' e2' e3') P.EWhere e ds ->- inferDs ds $ \ds1 -> do e1 <- checkE e tGoal- return (EWhere e1 ds1)+ do (e1,ds1) <- checkLocalDecls ds (checkE e tGoal)+ pure (EWhere e1 ds1) P.ETyped e t -> do tSig <- checkTypeOfKind t KType@@ -406,7 +458,7 @@ -- { _ | fs } ~~> \r -> { r | fs } Nothing ->- do r <- newParamName (packIdent "r")+ do r <- newParamName 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@@ -432,7 +484,7 @@ v1 <- checkE v (WithSource (tFun ft ft) src) -- XXX: ^ may be used a different src? d <- newHasGoal s (twsType tGoal) ft- tmp <- newParamName (packIdent "rf")+ tmp <- newParamName NSValue (packIdent "rf") let e' = EVar tmp pure $ hasDoSet d e' (EApp v1 (hasDoSelect d e')) `EWhere`@@ -581,10 +633,11 @@ checkFun ::- P.FunDesc Name -> [P.Pattern Name] -> P.Expr Name -> TypeWithSource -> InferM Expr+ P.FunDesc Name -> [P.Pattern Name] ->+ P.Expr Name -> TypeWithSource -> InferM Expr checkFun _ [] e tGoal = checkE e tGoal checkFun (P.FunDesc fun offset) ps e tGoal =- inNewScope $+ inNewScope do let descs = [ TypeOfArg (ArgDescr fun (Just n)) | n <- [ 1 + offset .. ] ] (tys,tRes) <- expectFun fun (length ps) tGoal@@ -965,68 +1018,104 @@ , dDoc = P.bDoc b } -inferDs :: FromDecl d => [d] -> ([DeclGroup] -> InferM a) -> InferM a-inferDs ds continue = either onErr checkTyDecls =<< orderTyDecls (mapMaybe toTyDecl ds)++--------------------------------------------------------------------------------+--------------------------------------------------------------------------------++checkLocalDecls :: [P.Decl Name] -> InferM a -> InferM (a,[DeclGroup])+checkLocalDecls ds0 k =+ do newLocalScope+ forM_ ds0 \d -> checkDecl False d Nothing+ a <- k+ (ds,_tySyns) <- endLocalScope+ pure (a,ds)++++checkTopDecls :: [P.TopDecl Name] -> InferM ()+checkTopDecls = mapM_ checkTopDecl where- onErr err = recordError err >> continue []+ checkTopDecl decl =+ case decl of+ P.Decl tl -> checkDecl True (P.tlValue tl) (thing <$> P.tlDoc tl) - isTopLevel = isTopDecl (head ds)+ P.TDNewtype tl ->+ do t <- checkNewtype (P.tlValue tl) (thing <$> P.tlDoc tl)+ addNewtype t - checkTyDecls (AT t mbD : ts) =- do t1 <- checkParameterType t mbD- withParamType t1 (checkTyDecls ts)+ P.DPrimType tl ->+ do t <- checkPrimType (P.tlValue tl) (thing <$> P.tlDoc tl)+ addPrimType t - checkTyDecls (TS t mbD : ts) =- do t1 <- checkTySyn t mbD- withTySyn t1 (checkTyDecls ts)+ P.DParameterType ty ->+ do t <- checkParameterType ty (P.ptDoc ty)+ addParamType t - checkTyDecls (PS t mbD : ts) =- do t1 <- checkPropSyn t mbD- withTySyn t1 (checkTyDecls ts)+ P.DParameterConstraint cs ->+ do cs1 <- checkParameterConstraints cs+ addParameterConstraints cs1 - checkTyDecls (NT t mbD : ts) =- do t1 <- checkNewtype t mbD- withNewtype t1 (checkTyDecls ts)+ P.DParameterFun pf ->+ do x <- checkParameterFun pf+ addParamFun x - checkTyDecls (PT p mbD : ts) =- do p1 <- checkPrimType p mbD- withPrimType p1 (checkTyDecls ts)+ 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 - -- We checked all type synonyms, now continue with value-level definitions:- checkTyDecls [] =- do cs <- checkParameterConstraints (concatMap toParamConstraints ds)- withParameterConstraints cs $- do xs <- mapM checkParameterFun (mapMaybe toParamFun ds)- withParamFuns xs $ checkBinds [] $ orderBinds $ mapMaybe toBind ds+ P.DImport {} -> pure ()+ P.Include {} -> panic "checkTopDecl" [ "Unexpected `inlude`" ] - checkParameterFun x =- do (s,gs) <- checkSchema NoWildCards (P.pfSchema x)- su <- proveImplication (Just (thing (P.pfName x)))- (sVars s) (sProps s) gs- unless (isEmptySubst su) $- panic "checkParameterFun" ["Subst not empty??"]- let n = thing (P.pfName x)- return ModVParam { mvpName = n- , mvpType = s- , mvpDoc = P.pfDoc x- , mvpFixity = P.pfFixity x- }+checkDecl :: Bool -> P.Decl Name -> Maybe Text -> InferM ()+checkDecl isTopLevel d mbDoc =+ case d of - checkBinds decls (CyclicSCC bs : more) =- do bs1 <- inferBinds isTopLevel True bs- foldr (\b m -> withVar (dName b) (dSignature b) m)- (checkBinds (Recursive bs1 : decls) more)- bs1+ P.DBind c ->+ do ~[b] <- inferBinds isTopLevel False [c]+ addDecls (NonRecursive b) - checkBinds decls (AcyclicSCC c : more) =- do ~[b] <- inferBinds isTopLevel False [c]- withVar (dName b) (dSignature b) $- checkBinds (NonRecursive b : decls) more+ P.DRec bs ->+ do bs1 <- inferBinds isTopLevel True bs+ addDecls (Recursive bs1) - -- We are done with all value-level definitions.- -- Now continue with anything that's in scope of the declarations.- checkBinds decls [] = continue (reverse decls)+ P.DType t ->+ do t1 <- checkTySyn t mbDoc+ addTySyn t1++ P.DProp t ->+ do t1 <- checkPropSyn t mbDoc+ addTySyn t1++ P.DLocated d' r -> inRange r (checkDecl isTopLevel d' mbDoc)++ P.DSignature {} -> bad "DSignature"+ P.DFixity {} -> bad "DFixity"+ P.DPragma {} -> bad "DPragma"+ P.DPatBind {} -> bad "DPatBind"++ where+ bad x = panic "checkDecl" [x]+++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+ unless (isEmptySubst su) $+ panic "checkParameterFun" ["Subst not empty??"]+ let n = thing (P.pfName x)+ return ModVParam { mvpName = n+ , mvpType = s+ , mvpDoc = P.pfDoc x+ , mvpFixity = P.pfFixity x+ }++ tcPanic :: String -> [String] -> a tcPanic l msg = panic ("[TypeCheck] " ++ l) msg
src/Cryptol/TypeCheck/InferTypes.hs view
@@ -48,6 +48,18 @@ } deriving (Show, Generic, NFData) +-- | A default configuration for using Z3, where+-- the solver prelude is expected to be found+-- in the given search path.+defaultSolverConfig :: [FilePath] -> SolverConfig+defaultSolverConfig searchPath =+ SolverConfig+ { solverPath = "z3"+ , solverArgs = [ "-smt2", "-in" ]+ , solverVerbose = 0+ , solverPreludePath = searchPath+ }+ -- | The types of variables in the environment. data VarType = ExtVar Schema -- ^ Known type@@ -303,24 +315,25 @@ addTVarsDescsAfter :: FVS t => NameMap -> t -> Doc -> Doc addTVarsDescsAfter nm t d | Set.null vs = d+-- TODO? use `hang` here instead to indent things after "where" | otherwise = d $$ text "where" $$ vcat (map desc (Set.toList vs)) where vs = fvs t desc v = ppWithNames nm v <+> text "is" <+> pp (tvInfo v) addTVarsDescsBefore :: FVS t => NameMap -> t -> Doc -> Doc-addTVarsDescsBefore nm t d = frontMsg $$ d $$ backMsg+addTVarsDescsBefore nm t d = vcat (frontMsg ++ [d] ++ backMsg) where (vs1,vs2) = Set.partition isFreeTV (fvs t) - frontMsg | null vs1 = empty- | otherwise = "Failed to infer the following types:"- $$ nest 2 (vcat (map desc1 (Set.toList vs1)))+ frontMsg | null vs1 = []+ | otherwise = [hang "Failed to infer the following types:"+ 2 (vcat (map desc1 (Set.toList vs1)))] desc1 v = "•" <+> ppWithNames nm v <.> comma <+> pp (tvInfo v) - backMsg | null vs2 = empty- | otherwise = "where"- $$ nest 2 (vcat (map desc2 (Set.toList vs2)))+ backMsg | null vs2 = []+ | otherwise = [hang "where"+ 2 (vcat (map desc2 (Set.toList vs2)))] desc2 v = ppWithNames nm v <+> text "is" <+> pp (tvInfo v) @@ -351,7 +364,7 @@ | prim == "infFromThen" -> "infinite enumeration (with step)" | prim == "fromTo" -> "finite enumeration" | prim == "fromThenTo" -> "finite enumeration"- _ -> "expression" <+> pp expr+ _ -> "expression" <+> pp expr where isPrelPrim x = do PrimIdent p i <- asPrim x guard (p == preludeName)@@ -359,19 +372,21 @@ instance PP (WithNames Goal) where ppPrec _ (WithNames g names) =- (ppWithNames names (goal g)) $$- nest 2 (text "arising from" $$- pp (goalSource g) $$- text "at" <+> pp (goalRange g))+ hang (ppWithNames names (goal g))+ 2 (text "arising from" $$+ pp (goalSource g) $$+ text "at" <+> pp (goalRange g)) instance PP (WithNames DelayedCt) where ppPrec _ (WithNames d names) =- sig $$ "we need to show that" $$- nest 2 (vcat [ vars, asmps, "the following constraints hold:"- , nest 2 $ vcat- $ bullets- $ map (ppWithNames ns1)- $ dctGoals d ])+ sig $$+ hang "we need to show that"+ 2 (vcat ( vars ++ asmps ++ + [ hang "the following constraints hold:"+ 2 (vcat+ $ bullets+ $ map (ppWithNames ns1)+ $ dctGoals d )])) where bullets xs = [ "•" <+> x | x <- xs ] @@ -382,12 +397,11 @@ name = dctSource d vars = case dctForall d of- [] -> empty- xs -> "for any type" <+>- fsep (punctuate comma (map (ppWithNames ns1 ) xs))+ [] -> []+ xs -> ["for any type" <+> commaSep (map (ppWithNames ns1) xs)] asmps = case dctAsmps d of- [] -> empty- xs -> "assuming" $$- nest 2 (vcat (bullets (map (ppWithNames ns1) xs)))+ [] -> []+ xs -> [hang "assuming"+ 2 (vcat (bullets (map (ppWithNames ns1) xs)))] ns1 = addTNames (dctForall d) names
+ src/Cryptol/TypeCheck/Interface.hs view
@@ -0,0 +1,73 @@+module Cryptol.TypeCheck.Interface where++import qualified Data.Map as Map++import Cryptol.Utils.Ident(Namespace(..))+import Cryptol.ModuleSystem.Interface+import Cryptol.TypeCheck.AST+++mkIfaceDecl :: Decl -> IfaceDecl+mkIfaceDecl d = IfaceDecl+ { ifDeclName = dName d+ , ifDeclSig = dSignature d+ , 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+ }+ }+ 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)++ (dPub,dPriv) =+ Map.partitionWithKey (\ qn _ -> qn `isExportedBind` mExports m)+ $ Map.fromList [ (qn,mkIfaceDecl d) | dg <- mDecls m+ , d <- groupDecls dg+ , let qn = dName d+ ]++ (mPub,mPriv) =+ Map.partitionWithKey (\ qn _ -> isExported NSModule qn (mExports m))+ $ mSubModules m++++
src/Cryptol/TypeCheck/Monad.hs view
@@ -13,11 +13,30 @@ {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE BlockArguments #-} module Cryptol.TypeCheck.Monad ( module Cryptol.TypeCheck.Monad , module Cryptol.TypeCheck.InferTypes ) where +import qualified Control.Applicative as A+import qualified Control.Monad.Fail as Fail+import Control.Monad.Fix(MonadFix(..))+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Map (Map)+import Data.Set (Set)+import Data.List(find, foldl')+import Data.List.NonEmpty(NonEmpty((:|)))+import Data.Semigroup(sconcat)+import Data.Maybe(mapMaybe,fromMaybe)+import Data.IORef++import GHC.Generics (Generic)+import Control.DeepSeq++import MonadLib hiding (mapM)+ import Cryptol.ModuleSystem.Name (FreshM(..),Supply,mkParameter , nameInfo, NameInfo(..),NameSource(..))@@ -25,6 +44,7 @@ import qualified Cryptol.Parser.AST as P import Cryptol.TypeCheck.AST import Cryptol.TypeCheck.Subst+import Cryptol.TypeCheck.Interface(genIface) import Cryptol.TypeCheck.Unify(mgu, runResult, UnificationError(..)) import Cryptol.TypeCheck.InferTypes import Cryptol.TypeCheck.Error( Warning(..),Error(..)@@ -34,26 +54,9 @@ 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)+import Cryptol.Utils.Ident(Ident,Namespace(..)) import Cryptol.Utils.Panic(panic) -import qualified Control.Applicative as A-import qualified Control.Monad.Fail as Fail-import Control.Monad.Fix(MonadFix(..))-import qualified Data.Map as Map-import qualified Data.Set as Set-import Data.Map (Map)-import Data.Set (Set)-import Data.List(find, foldl')-import Data.Maybe(mapMaybe,fromMaybe)-import MonadLib hiding (mapM)--import Data.IORef---import GHC.Generics (Generic)-import Control.DeepSeq- -- | Information needed for type inference. data InferInput = InferInput { inpRange :: Range -- ^ Location of program source@@ -76,7 +79,6 @@ , inpCallStacks :: Bool -- ^ Are we tracking call stacks? - , inpSolverConfig :: SolverConfig -- ^ Options for the constraint solver , inpSearchPath :: [FilePath] -- ^ Where to look for Cryptol theory file. @@ -119,16 +121,21 @@ runInferM :: TVars a => InferInput -> InferM a -> IO (InferOutput a) runInferM info (IM m) = do counter <- newIORef 0+ let env = Map.map ExtVar (inpVars info)+ <> Map.map (ExtVar . newtypeConType) (inpNewtypes info)+ rec ro <- return RO { iRange = inpRange info- , iVars = Map.map ExtVar (inpVars info)- , iTVars = []- , iTSyns = fmap mkExternal (inpTSyns info)- , iNewtypes = fmap mkExternal (inpNewtypes info)- , iAbstractTypes = mkExternal <$> inpAbstractTypes info- , iParamTypes = inpParamTypes info- , iParamFuns = inpParamFuns info- , iParamConstraints = inpParamConstraints info+ , iVars = env+ , iExtScope = (emptyModule ExternalScope)+ { mTySyns = inpTSyns info+ , mNewtypes = inpNewtypes info+ , mPrimTypes = inpAbstractTypes info+ , mParamTypes = inpParamTypes info+ , mParamFuns = inpParamFuns info+ , mParamConstraints = inpParamConstraints info+ } + , iTVars = [] , iSolvedHasLazy = iSolvedHas finalRW -- RECURSION , iMonoBinds = inpMonoBinds info , iCallStacks = inpCallStacks info@@ -168,7 +175,6 @@ in pure (InferFailed (computeFreeVarNames ws es1) ws es1) - mkExternal x = (IsExternal, x) rw = RW { iErrors = [] , iWarnings = [] , iSubst = emptySubst@@ -181,6 +187,9 @@ , iSolvedHas = Map.empty , iSupply = inpSupply info++ , iScope = []+ , iBindTypes = mempty } @@ -191,38 +200,28 @@ newtype InferM a = IM { unIM :: ReaderT RO (StateT RW IO) a } -data DefLoc = IsLocal | IsExternal +data ScopeName = ExternalScope+ | LocalScope+ | SubModule Name+ | MTopModule P.ModName+ -- | Read-only component of the monad. data RO = RO- { iRange :: Range -- ^ Source code being analysed- , iVars :: Map Name VarType -- ^ Type of variable that are in scope+ { iRange :: Range -- ^ Source code being analysed+ , iVars :: Map Name VarType+ -- ^ Type of variable that are in scope+ -- These are only parameters vars that are in recursive component we+ -- are checking at the moment. If a var is not there, keep looking in+ -- the 'iScope' - {- NOTE: We assume no shadowing between these two, so it does not matter- where we look first. Similarly, we assume no shadowing with- the existential type variable (in RW). See 'checkTShadowing'. -} - , iTVars :: [TParam] -- ^ Type variable that are in scope- , iTSyns :: Map Name (DefLoc, TySyn) -- ^ Type synonyms that are in scope- , iNewtypes :: Map Name (DefLoc, Newtype)- -- ^ Newtype declarations in scope- --- -- NOTE: type synonyms take precedence over newtype. The reason is- -- that we can define local type synonyms, but not local newtypes.- -- So, either a type-synonym shadows a newtype, or it was declared- -- at the top-level, but then there can't be a newtype with the- -- same name (this should be caught by the renamer).- , iAbstractTypes :: Map Name (DefLoc, AbstractType)-- , iParamTypes :: Map Name ModTParam- -- ^ Parameter types-- , iParamConstraints :: [Located Prop]- -- ^ Constraints on the type parameters-- , iParamFuns :: Map Name ModVParam- -- ^ Parameter functions+ , iTVars :: [TParam] -- ^ Type variable that are in scope + , 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 , iSolvedHasLazy :: Map Int HasGoalSln -- ^ NOTE: This field is lazy in an important way! It is the@@ -278,9 +277,17 @@ {- ^ Tuple/record projection constraints. The 'Int' is the "name" of the constraint, used so that we can name its solution properly. -} + , iScope :: ![ModuleG ScopeName]+ -- ^ Nested scopes we are currently checking, most nested first.++ , iBindTypes :: !(Map Name Schema)+ -- ^ Types of variables that we know about. We don't worry about scoping+ -- here because we assume the bindings all have different names.+ , iSupply :: !Supply } + instance Functor InferM where fmap f (IM m) = IM (fmap f m) @@ -452,10 +459,10 @@ -------------------------------------------------------------------------------- -- | Generate a fresh variable name to be used in a local binding.-newParamName :: Ident -> InferM Name-newParamName x =+newParamName :: Namespace -> Ident -> InferM Name+newParamName ns x = do r <- curRange- liftSupply (mkParameter x r)+ liftSupply (mkParameter ns x r) newName :: (NameSeeds -> (a , NameSeeds)) -> InferM a newName upd = IM $ sets $ \s -> let (x,seeds) = upd (iNameSeeds s)@@ -634,17 +641,13 @@ lookupVar x = do mb <- IM $ asks $ Map.lookup x . iVars case mb of- Just t -> return t+ Just a -> pure a Nothing ->- do mbNT <- lookupNewtype x- case mbNT of- Just nt -> return (ExtVar (newtypeConType nt))- Nothing ->- do mbParamFun <- lookupParamFun x- case mbParamFun of- Just pf -> return (ExtVar (mvpType pf))- Nothing -> panic "lookupVar" [ "Undefined type variable"- , show x]+ do mb1 <- Map.lookup x . iBindTypes <$> IM get+ case mb1 of+ Just a -> pure (ExtVar a)+ Nothing -> panic "lookupVar" [ "Undefined vairable"+ , show x ] -- | 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.@@ -654,14 +657,14 @@ -- | Lookup the definition of a type synonym. lookupTSyn :: Name -> InferM (Maybe TySyn)-lookupTSyn x = fmap (fmap snd . Map.lookup x) getTSyns+lookupTSyn x = Map.lookup x <$> getTSyns -- | Lookup the definition of a newtype lookupNewtype :: Name -> InferM (Maybe Newtype)-lookupNewtype x = fmap (fmap snd . Map.lookup x) getNewtypes+lookupNewtype x = Map.lookup x <$> getNewtypes lookupAbstractType :: Name -> InferM (Maybe AbstractType)-lookupAbstractType x = fmap (fmap snd . Map.lookup x) getAbstractTypes+lookupAbstractType x = Map.lookup x <$> getAbstractTypes -- | Lookup the kind of a parameter type lookupParamType :: Name -> InferM (Maybe ModTParam)@@ -693,28 +696,28 @@ -- | Returns the type synonyms that are currently in scope.-getTSyns :: InferM (Map Name (DefLoc,TySyn))-getTSyns = IM $ asks iTSyns+getTSyns :: InferM (Map Name TySyn)+getTSyns = getScope mTySyns -- | Returns the newtype declarations that are in scope.-getNewtypes :: InferM (Map Name (DefLoc,Newtype))-getNewtypes = IM $ asks iNewtypes+getNewtypes :: InferM (Map Name Newtype)+getNewtypes = getScope mNewtypes -- | Returns the abstract type declarations that are in scope.-getAbstractTypes :: InferM (Map Name (DefLoc,AbstractType))-getAbstractTypes = IM $ asks iAbstractTypes+getAbstractTypes :: InferM (Map Name AbstractType)+getAbstractTypes = getScope mPrimTypes -- | Returns the parameter functions declarations getParamFuns :: InferM (Map Name ModVParam)-getParamFuns = IM $ asks iParamFuns+getParamFuns = getScope mParamFuns -- | Returns the abstract function declarations getParamTypes :: InferM (Map Name ModTParam)-getParamTypes = IM $ asks iParamTypes+getParamTypes = getScope mParamTypes -- | Constraints on the module's parameters. getParamConstraints :: InferM [Located Prop]-getParamConstraints = IM $ asks iParamConstraints+getParamConstraints = getScope mParamConstraints -- | Get the set of bound type variables that are in scope. getTVars :: InferM (Set Name)@@ -724,8 +727,8 @@ getBoundInScope :: InferM (Set TParam) getBoundInScope = do ro <- IM ask- let params = Set.fromList (map mtpParam (Map.elems (iParamTypes ro)))- bound = Set.fromList (iTVars ro)+ params <- Set.fromList . map mtpParam . Map.elems <$> getParamTypes+ let bound = Set.fromList (iTVars ro) return $! Set.union params bound -- | Retrieve the value of the `mono-binds` option.@@ -740,12 +743,14 @@ need to worry about where we lookup things (i.e., in the variable or type synonym environment. -} +-- XXX: this should be done in renamer checkTShadowing :: String -> Name -> InferM () checkTShadowing this new =- do ro <- IM ask+ do tsyns <- getTSyns+ ro <- IM ask rw <- IM get let shadowed =- do _ <- Map.lookup new (iTSyns ro)+ do _ <- Map.lookup new tsyns return "type synonym" `mplus` do guard (new `elem` mapMaybe tpName (iTVars ro))@@ -760,7 +765,6 @@ recordError (TypeShadowing this new that) - -- | The sub-computation is performed with the given type parameter in scope. withTParam :: TParam -> InferM a -> InferM a withTParam p (IM m) =@@ -772,32 +776,148 @@ withTParams :: [TParam] -> InferM a -> InferM a withTParams ps m = foldr withTParam m ps ++-- | Execute the given computation in a new top scope.+-- The sub-computation would typically be validating a module.+newScope :: ScopeName -> InferM ()+newScope nm = IM $ sets_ \rw -> rw { iScope = emptyModule nm : iScope rw }++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 }++newModuleScope :: P.ModName -> [Import] -> ExportSpec Name -> InferM ()+newModuleScope x is e =+ do newScope (MTopModule x)+ updScope \m -> m { mImports = is, mExports = e }++-- | Update the current scope (first in the list). Assumes there is one.+updScope :: (ModuleG ScopeName -> ModuleG ScopeName) -> InferM ()+updScope f = IM $ sets_ \rw -> rw { iScope = upd (iScope rw) }+ where+ upd r =+ case r of+ [] -> panic "updTopScope" [ "No top scope" ]+ s : more -> f s : more++endLocalScope :: InferM ([DeclGroup], Map Name TySyn)+endLocalScope =+ IM $ sets \rw ->+ case iScope rw of+ x : xs | LocalScope <- mName x ->+ ( (reverse (mDecls x), mTySyns x), rw { iScope = xs })++ _ -> panic "endLocalScope" ["Missing local scope"]++endSubmodule :: InferM ()+endSubmodule =+ IM $ sets_ \rw ->+ 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)++ , 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+ }++ _ -> panic "endSubmodule" [ "Not a submodule" ]+++endModule :: InferM Module+endModule =+ IM $ sets \rw ->+ case iScope rw of+ [ x ] | MTopModule m <- mName x ->+ ( x { mName = m, mDecls = reverse (mDecls x) }+ , rw { iScope = [] }+ )+ _ -> panic "endModule" [ "Not a single top module" ]++endModuleInstance :: InferM ()+endModuleInstance =+ IM $ sets_ \rw ->+ case iScope rw of+ [ x ] | MTopModule _ <- mName x -> rw { iScope = [] }+ _ -> panic "endModuleInstance" [ "Not single top module" ]+++-- | Get an environment combining all nested scopes.+getScope :: Semigroup a => (ModuleG ScopeName -> a) -> InferM a+getScope f =+ do ro <- IM ask+ rw <- IM get+ pure (sconcat (f (iExtScope ro) :| map f (iScope rw)))++addDecls :: DeclGroup -> InferM ()+addDecls ds =+ do updScope \r -> r { mDecls = ds : mDecls r }+ IM $ sets_ \rw -> rw { iBindTypes = new rw }+ where+ add d = Map.insert (dName d) (dSignature d)+ new rw = foldr add (iBindTypes rw) (groupDecls ds)+ -- | The sub-computation is performed with the given type-synonym in scope.-withTySyn :: TySyn -> InferM a -> InferM a-withTySyn t (IM m) =+addTySyn :: TySyn -> InferM ()+addTySyn t = do let x = tsName t checkTShadowing "synonym" x- IM $ mapReader (\r -> r { iTSyns = Map.insert x (IsLocal,t) (iTSyns r) }) m+ updScope \r -> r { mTySyns = Map.insert x t (mTySyns r) } -withNewtype :: Newtype -> InferM a -> InferM a-withNewtype t (IM m) =- IM $ mapReader- (\r -> r { iNewtypes = Map.insert (ntName t) (IsLocal,t)- (iNewtypes r) }) m+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)+ (newtypeConType t)+ (iBindTypes rw) } -withPrimType :: AbstractType -> InferM a -> InferM a-withPrimType t (IM m) =- IM $ mapReader- (\r -> r { iAbstractTypes = Map.insert (atName t) (IsLocal,t)- (iAbstractTypes r) }) m+addPrimType :: AbstractType -> InferM ()+addPrimType t =+ 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) } -withParamType :: ModTParam -> InferM a -> InferM a-withParamType a (IM m) =- IM $ mapReader- (\r -> r { iParamTypes = Map.insert (mtpName a) a (iParamTypes r) })- m+-- | The sub-computation is performed with the given abstract function in scope.+addParamFun :: ModVParam -> InferM ()+addParamFun x =+ do updScope \r -> r { mParamFuns = Map.insert (mvpName x) x (mParamFuns r) }+ IM $ sets_ \rw -> rw { iBindTypes = Map.insert (mvpName x) (mvpType x)+ (iBindTypes rw) } +-- | Add some assumptions for an entire module+addParameterConstraints :: [Located Prop] -> InferM ()+addParameterConstraints ps =+ updScope \r -> r { mParamConstraints = ps ++ mParamConstraints r }+++++-- | Perform the given computation in a new scope (i.e., the subcomputation+-- may use existential type variables). This is a different kind of scope+-- from the nested modules one.+inNewScope :: InferM a -> InferM a+inNewScope m =+ do curScopes <- iExistTVars <$> IM get+ IM $ sets_ $ \s -> s { iExistTVars = Map.empty : curScopes }+ a <- m+ IM $ sets_ $ \s -> s { iExistTVars = curScopes }+ return a++ -- | The sub-computation is performed with the given variable in scope. withVarType :: Name -> VarType -> InferM a -> InferM a withVarType x s (IM m) =@@ -809,19 +929,6 @@ withVar :: Name -> Schema -> InferM a -> InferM a withVar x s = withVarType x (ExtVar s) --- | The sub-computation is performed with the given abstract function in scope.-withParamFuns :: [ModVParam] -> InferM a -> InferM a-withParamFuns xs (IM m) =- IM $ mapReader (\r -> r { iParamFuns = foldr add (iParamFuns r) xs }) m- where- add x = Map.insert (mvpName x) x---- | Add some assumptions for an entire module-withParameterConstraints :: [Located Prop] -> InferM a -> InferM a-withParameterConstraints ps (IM m) =- IM $ mapReader (\r -> r { iParamConstraints = ps ++ iParamConstraints r }) m-- -- | The sub-computation is performed with the given variables in scope. withMonoType :: (Name,Located Type) -> InferM a -> InferM a withMonoType (x,lt) = withVar x (Forall [] [] (thing lt))@@ -829,25 +936,6 @@ -- | The sub-computation is performed with the given variables in scope. withMonoTypes :: Map Name (Located Type) -> InferM a -> InferM a withMonoTypes xs m = foldr withMonoType m (Map.toList xs)---- | The sub-computation is performed with the given type synonyms--- and variables in scope.-withDecls :: ([TySyn], Map Name Schema) -> InferM a -> InferM a-withDecls (ts,vs) m = foldr withTySyn (foldr add m (Map.toList vs)) ts- where- add (x,t) = withVar x t---- | Perform the given computation in a new scope (i.e., the subcomputation--- may use existential type variables).-inNewScope :: InferM a -> InferM a-inNewScope m =- do curScopes <- iExistTVars <$> IM get- IM $ sets_ $ \s -> s { iExistTVars = Map.empty : curScopes }- a <- m- IM $ sets_ $ \s -> s { iExistTVars = curScopes }- return a-- -------------------------------------------------------------------------------- -- Kind checking
src/Cryptol/TypeCheck/Parseable.hs view
@@ -17,18 +17,30 @@ , ShowParseable(..) ) where +import Data.Void+import Prettyprinter+ import Cryptol.TypeCheck.AST import Cryptol.Utils.Ident (Ident,unpackIdent) import Cryptol.Utils.RecordMap (canonicalFields) import Cryptol.Parser.AST ( Located(..)) import Cryptol.ModuleSystem.Name-import Text.PrettyPrint hiding ((<>))-import qualified Text.PrettyPrint as PP ((<>)) ++infixl 5 $$+($$) :: Doc a -> Doc a -> Doc a+($$) x y = sep [x, y]++text :: String -> Doc a+text = pretty++int :: Int -> Doc a+int = pretty+ -- ShowParseable prints out a cryptol program in a way that it's parseable by Coq (and likely other things) -- Used mainly for reasoning about the semantics of cryptol programs in Coq (https://github.com/GaloisInc/cryptol-semantics) class ShowParseable t where- showParseable :: t -> Doc+ showParseable :: t -> Doc Void instance ShowParseable Expr where showParseable (ELocated _ e) = showParseable e -- TODO? emit range information@@ -53,7 +65,7 @@ showParseable (EProofApp e) = showParseable e --"(EProofApp " ++ showParseable e ++ ")" instance (ShowParseable a, ShowParseable b) => ShowParseable (a,b) where- showParseable (x,y) = parens (showParseable x PP.<> comma PP.<> showParseable y)+ showParseable (x,y) = parens (showParseable x <> comma <> showParseable y) instance ShowParseable Int where showParseable i = int i@@ -105,11 +117,11 @@ showParseable l = showParseable (thing l) instance ShowParseable TParam where- showParseable tp = parens (text (show (tpUnique tp)) PP.<> comma PP.<> maybeNameDoc (tpName tp))+ showParseable tp = parens (text (show (tpUnique tp)) <> comma <> maybeNameDoc (tpName tp)) -maybeNameDoc :: Maybe Name -> Doc-maybeNameDoc Nothing = doubleQuotes empty+maybeNameDoc :: Maybe Name -> Doc Void+maybeNameDoc Nothing = dquotes mempty maybeNameDoc (Just n) = showParseable (nameIdent n) instance ShowParseable Name where- showParseable n = parens (text (show (nameUnique n)) PP.<> comma PP.<> showParseable (nameIdent n))+ showParseable n = parens (text (show (nameUnique n)) <> comma <> showParseable (nameIdent n))
src/Cryptol/TypeCheck/SimpType.hs view
@@ -182,7 +182,6 @@ tCeilDiv :: Type -> Type -> Type tCeilDiv x y | Just t <- tOp TCCeilDiv (op2 nCeilDiv) [x,y] = t- | tIsInf x = bad | tIsInf y = bad | Just 0 <- tIsNum y = bad | otherwise = tf2 TCCeilDiv x y@@ -191,7 +190,6 @@ tCeilMod :: Type -> Type -> Type tCeilMod x y | Just t <- tOp TCCeilMod (op2 nCeilMod) [x,y] = t- | tIsInf x = bad | tIsInf y = bad | Just 0 <- tIsNum x = bad | otherwise = tf2 TCCeilMod x y@@ -264,6 +262,12 @@ maxK (Nat 0) t = t maxK (Nat k) t + -- max 1 t ~> t, if t = a ^ b && a >= 1+ | k == 1+ , TCon (TF TCExp) [a,_] <- t'+ , Just base <- tIsNat' a+ , base >= Nat 1 = t+ | TCon (TF TCAdd) [a,b] <- t' , Just n <- tIsNum a = if k <= n then t@@ -285,6 +289,13 @@ tWidth :: Type -> Type tWidth x | Just t <- tOp TCWidth (total (op1 nWidth)) [x] = t++ -- width (2^n - 1) = n+ | TCon (TF TCSub) [a,b] <- tNoUser x+ , Just 1 <- tIsNum b+ , TCon (TF TCExp) [p,q] <- tNoUser a+ , Just 2 <- tIsNum p = q+ | otherwise = tf1 TCWidth x tLenFromThenTo :: Type -> Type -> Type -> Type
src/Cryptol/TypeCheck/SimpleSolver.hs view
@@ -30,8 +30,7 @@ SolvedIf ps -> dbg msg $ pAnd (map (simplify ctxt) ps) where msg = case ps of [] -> text "solved:" <+> pp p- _ -> pp p <+> text "~~~>" <+>- vcat (punctuate comma (map pp ps))+ _ -> pp p <+> text "~~~>" <+> commaSep (map pp ps) where dbg msg x
src/Cryptol/TypeCheck/Solver/InfNat.hs view
@@ -122,23 +122,22 @@ nMod (Nat x) Inf = Just (Nat x) -- inf * 0 + x = 0 + x -- | @nCeilDiv msgLen blockSize@ computes the least @n@ such that--- @msgLen <= blockSize * n@. It is undefined when @blockSize = 0@.--- It is also undefined when either input is infinite; perhaps this--- could be relaxed later.+-- @msgLen <= blockSize * n@. It is undefined when @blockSize = 0@,+-- or when @blockSize = inf@. @inf@ divided by any positive+-- finite value is @inf@. nCeilDiv :: Nat' -> Nat' -> Maybe Nat'+nCeilDiv _ Inf = Nothing nCeilDiv _ (Nat 0) = Nothing-nCeilDiv Inf _ = Nothing-nCeilDiv (Nat _) Inf = Nothing+nCeilDiv Inf (Nat _) = Just Inf nCeilDiv (Nat x) (Nat y) = Just (Nat (- div (- x) y)) -- | @nCeilMod msgLen blockSize@ computes the least @k@ such that--- @blockSize@ divides @msgLen + k@. It is undefined when @blockSize = 0@.--- It is also undefined when either input is infinite; perhaps this--- could be relaxed later.+-- @blockSize@ divides @msgLen + k@. It is undefined when @blockSize = 0@+-- or @blockSize = inf@. @inf@ modulus any positive finite value is @0@. nCeilMod :: Nat' -> Nat' -> Maybe Nat'+nCeilMod _ Inf = Nothing nCeilMod _ (Nat 0) = Nothing-nCeilMod Inf _ = Nothing-nCeilMod (Nat _) Inf = Nothing+nCeilMod Inf (Nat _) = Just (Nat 0) nCeilMod (Nat x) (Nat y) = Just (Nat (mod (- x) y)) -- | Rounds up.
src/Cryptol/TypeCheck/Solver/Numeric/Fin.hs view
@@ -56,7 +56,7 @@ i2 = typeInterval varInfo t2 - (TCDiv, [t1,_]) -> SolvedIf [ pFin t1 ]+ (TCDiv, [_,_]) -> SolvedIf [] (TCMod, [_,_]) -> SolvedIf [] -- fin (x ^ y)@@ -85,7 +85,7 @@ (TCMax, [t1,t2]) -> SolvedIf [ pFin t1, pFin t2 ] (TCWidth, [t1]) -> SolvedIf [ pFin t1 ]- (TCCeilDiv, [_,_]) -> SolvedIf []+ (TCCeilDiv, [t1,_]) -> SolvedIf [ pFin t1 ] (TCCeilMod, [_,_]) -> SolvedIf [] (TCLenFromThenTo,[_,_,_]) -> SolvedIf []
src/Cryptol/TypeCheck/Solver/SMT.hs view
@@ -15,10 +15,12 @@ module Cryptol.TypeCheck.Solver.SMT ( -- * Setup Solver+ , SolverConfig , withSolver , startSolver , stopSolver , isNumeric+ , resetSolver -- * Debugging , debugBlock@@ -53,7 +55,7 @@ import Cryptol.TypeCheck.TypePat hiding ((~>),(~~>)) import Cryptol.TypeCheck.Subst(Subst) import Cryptol.Utils.Panic-import Cryptol.Utils.PP -- ( Doc )+import Cryptol.Utils.PP ( Doc, pp ) @@ -67,18 +69,22 @@ -- ^ For debugging } +setupSolver :: Solver -> SolverConfig -> IO ()+setupSolver s cfg = do+ _ <- SMT.setOptionMaybe (solver s) ":global-decls" "false"+ loadTcPrelude s (solverPreludePath cfg)+ -- | Start a fresh solver instance-startSolver :: SolverConfig -> IO Solver-startSolver SolverConfig { .. } =- do logger <- if solverVerbose > 0 then SMT.newLogger 0+startSolver :: IO () -> SolverConfig -> IO Solver+startSolver onExit sCfg =+ do logger <- if (solverVerbose sCfg) > 0 then SMT.newLogger 0 else return quietLogger- let smtDbg = if solverVerbose > 1 then Just logger else Nothing- solver <- SMT.newSolver solverPath solverArgs smtDbg- _ <- SMT.setOptionMaybe solver ":global-decls" "false"- -- SMT.setLogic solver "QF_LIA"- let sol = Solver { .. }- loadTcPrelude sol solverPreludePath+ let smtDbg = if (solverVerbose sCfg) > 1 then Just logger else Nothing+ solver <- SMT.newSolverNotify+ (solverPath sCfg) (solverArgs sCfg) smtDbg (Just (const onExit))+ let sol = Solver solver logger+ setupSolver sol sCfg return sol where@@ -93,9 +99,14 @@ stopSolver :: Solver -> IO () stopSolver s = void $ SMT.stop (solver s) +resetSolver :: Solver -> SolverConfig -> IO ()+resetSolver s sCfg = do+ _ <- SMT.simpleCommand (solver s) ["reset"]+ setupSolver s sCfg+ -- | Execute a computation with a fresh solver instance.-withSolver :: SolverConfig -> (Solver -> IO a) -> IO a-withSolver cfg = bracket (startSolver cfg) stopSolver+withSolver :: IO () -> SolverConfig -> (Solver -> IO a) -> IO a+withSolver onExit cfg = bracket (startSolver onExit cfg) stopSolver -- | Load the definitions used for type checking. loadTcPrelude :: Solver -> [FilePath] {- ^ Search in this paths -} -> IO ()
src/Cryptol/TypeCheck/Solver/Selector.hs view
@@ -15,7 +15,7 @@ , newParamName ) import Cryptol.TypeCheck.Subst (listParamSubst, apSubst)-import Cryptol.Utils.Ident (Ident, packIdent)+import Cryptol.Utils.Ident (Ident, packIdent,Namespace(..)) import Cryptol.Utils.Panic(panic) import Cryptol.Utils.RecordMap @@ -163,9 +163,9 @@ -- xs.s ~~> [ x.s | x <- xs ] -- { xs | s = ys } ~~> [ { x | s = y } | x <- xs | y <- ys ] liftSeq len el =- do x1 <- newParamName (packIdent "x")- x2 <- newParamName (packIdent "x")- y2 <- newParamName (packIdent "y")+ do x1 <- newParamName NSValue (packIdent "x")+ x2 <- newParamName NSValue (packIdent "x")+ y2 <- newParamName NSValue (packIdent "y") case tNoUser innerT of TCon _ [_,eli] -> do d <- mkSelSln s el eli@@ -187,8 +187,8 @@ -- f.s ~~> \x -> (f x).s -- { f | s = g } ~~> \x -> { f x | s = g x } liftFun t1 t2 =- do x1 <- newParamName (packIdent "x")- x2 <- newParamName (packIdent "x")+ do x1 <- newParamName NSValue (packIdent "x")+ x2 <- newParamName NSValue (packIdent "x") case tNoUser innerT of TCon _ [_,inT] -> do d <- mkSelSln s t2 inT
src/Cryptol/TypeCheck/Subst.hs view
@@ -336,6 +336,14 @@ (cons k) } +instance TVars a => TVars (Map.Map k a) where+ -- NB, strict map+ apSubst su m = Map.map (apSubst su) m++instance TVars TySyn where+ apSubst su (TySyn nm params props t doc) =+ (\props' t' -> TySyn nm params props' t' doc)+ !$ apSubst su props !$ apSubst su t {- | This instance does not need to worry about bound variable capture, because we rely on the 'Subst' datatype invariant to ensure
src/Cryptol/TypeCheck/TCon.hs view
@@ -41,9 +41,9 @@ builtInType nm = case M.nameInfo nm of M.Declared m _- | m == preludeName -> Map.lookup (M.nameIdent nm) builtInTypes- | m == floatName -> Map.lookup (M.nameIdent nm) builtInFloat- | m == arrayName -> Map.lookup (M.nameIdent nm) builtInArray+ | 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 _ -> Nothing where
src/Cryptol/TypeCheck/Type.hs view
@@ -2,6 +2,11 @@ {-# Language FlexibleInstances, FlexibleContexts #-} {-# Language PatternGuards #-} {-# Language OverloadedStrings #-}+{-| This module contains types related to typechecking and the output of the+typechecker. In particular, it should contain the types needed by+interface files (see 'Crytpol.ModuleSystem.Interface'), which are (kind of)+the output of the typechker.+-} module Cryptol.TypeCheck.Type ( module Cryptol.TypeCheck.Type , module Cryptol.TypeCheck.TCon@@ -32,8 +37,40 @@ infix 4 =#=, >== infixr 5 `tFun` +-- | 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) +mtpParam :: ModTParam -> TParam+mtpParam mtp = TParam { tpUnique = nameUnique (mtpName mtp)+ , tpKind = mtpKind mtp+ , tpFlav = TPModParam (mtpName mtp)+ , tpInfo = desc+ }+ where desc = TVarInfo { tvarDesc = TVFromModParam (mtpName mtp)+ , tvarSource = nameLoc (mtpName mtp)+ }++-- | A value parameter of a module.+data ModVParam = ModVParam+ { mvpName :: Name+ , mvpType :: Schema+ , mvpDoc :: Maybe Text+ , mvpFixity :: Maybe Fixity+ } deriving (Show,Generic,NFData)+++++ -- | The types of polymorphic values. data Schema = Forall { sVars :: [TParam], sProps :: [Prop], sType :: Type } deriving (Eq, Show, Generic, NFData)@@ -893,17 +930,17 @@ instance PP (WithNames Schema) where ppPrec _ (WithNames s ns) | null (sVars s) && null (sProps s) = body- | otherwise = hang (vars <+> props) 2 body+ | otherwise = nest 2 (sep (vars ++ props ++ [body])) where body = ppWithNames ns1 (sType s) vars = case sVars s of- [] -> empty- vs -> braces $ commaSep $ map (ppWithNames ns1) vs+ [] -> []+ vs -> [nest 1 (braces (commaSepFill (map (ppWithNames ns1) vs)))] props = case sProps s of- [] -> empty- ps -> parens (commaSep (map (ppWithNames ns1) ps)) <+> text "=>"+ [] -> []+ ps -> [nest 1 (parens (commaSepFill (map (ppWithNames ns1) ps))) <+> text "=>"] ns1 = addTNames (sVars s) ns @@ -912,17 +949,20 @@ instance PP (WithNames TySyn) where ppPrec _ (WithNames ts ns) =- text "type" <+> ctr <+> lhs <+> char '=' <+> ppWithNames ns1 (tsDef ts)+ nest 2 $ sep+ [ fsep ([text "type"] ++ ctr ++ lhs ++ [char '='])+ , ppWithNames ns1 (tsDef ts)+ ] where ns1 = addTNames (tsParams ts) ns ctr = case kindResult (kindOf ts) of- KProp -> text "constraint"- _ -> empty+ KProp -> [text "constraint"]+ _ -> [] n = tsName ts lhs = case (nameFixity n, tsParams ts) of (Just _, [x, y]) ->- ppWithNames ns1 x <+> pp (nameIdent n) <+> ppWithNames ns1 y+ [ppWithNames ns1 x, pp (nameIdent n), ppWithNames ns1 y] (_, ps) ->- pp n <+> sep (map (ppWithNames ns1) ps)+ [pp n] ++ map (ppWithNames ns1) ps instance PP Newtype where ppPrec = ppWithNamesPrec IntMap.empty@@ -948,8 +988,8 @@ ppPrec prec ty0@(WithNames ty nmMap) = case ty of TVar a -> ppWithNames nmMap a- TNewtype nt ts -> optParens (prec > 3) $ pp (ntName nt) <+> fsep (map (go 5) ts)- TRec fs -> braces $ fsep $ punctuate comma+ TNewtype nt ts -> optParens (prec > 3) $ fsep (pp (ntName nt) : map (go 5) ts)+ TRec fs -> ppRecord [ pp l <+> text ":" <+> go 0 t | (l,t) <- displayFields fs ] _ | Just tinf <- isTInfix ty0 -> optParens (prec > 2)@@ -957,14 +997,13 @@ TUser c ts t -> withNameDisp $ \disp ->- case nameInfo c of- Declared m _- | NotInScope <- getNameFormat m (nameIdent c) disp ->+ case asOrigName c of+ Just og | NotInScope <- getNameFormat og disp -> go prec t -- unfold type synonym if not in scope _ -> case ts of [] -> pp c- _ -> optParens (prec > 3) $ pp c <+> fsep (map (go 5) ts)+ _ -> optParens (prec > 3) $ fsep (pp c : map (go 5) ts) TCon (TC tc) ts -> case (tc,ts) of@@ -983,9 +1022,9 @@ (TCFun, [t1,t2]) -> optParens (prec > 1) $ go 2 t1 <+> text "->" <+> go 1 t2 - (TCTuple _, fs) -> parens $ fsep $ punctuate comma $ map (go 0) fs+ (TCTuple _, fs) -> ppTuple $ map (go 0) fs - (_, _) -> optParens (prec > 3) $ pp tc <+> fsep (map (go 5) ts)+ (_, _) -> optParens (prec > 3) $ fsep (pp tc : (map (go 5) ts)) TCon (PC pc) ts -> case (pc,ts) of@@ -996,7 +1035,7 @@ (PPrime, [t1]) -> optParens (prec > 3) $ text "prime" <+> (go 5 t1) (PHas x, [t1,t2]) -> ppSelector x <+> text "of" <+> go 0 t1 <+> text "is" <+> go 0 t2- (PAnd, [t1,t2]) -> parens (commaSep (map (go 0) (t1 : pSplitAnd t2)))+ (PAnd, [t1,t2]) -> nest 1 (parens (commaSepFill (map (go 0) (t1 : pSplitAnd t2)))) (PRing, [t1]) -> pp pc <+> go 5 t1 (PField, [t1]) -> pp pc <+> go 5 t1@@ -1008,10 +1047,9 @@ (PLiteral, [t1,t2]) -> pp pc <+> go 5 t1 <+> go 5 t2 (PLiteralLessThan, [t1,t2]) -> pp pc <+> go 5 t1 <+> go 5 t2 - (_, _) -> optParens (prec > 3) $ pp pc <+> fsep (map (go 5) ts)+ (_, _) -> optParens (prec > 3) $ fsep (pp pc : map (go 5) ts) - TCon f ts -> optParens (prec > 3)- $ pp f <+> fsep (map (go 5) ts)+ TCon f ts -> optParens (prec > 3) $ fsep (pp f : map (go 5) ts) where go p t = ppWithNamesPrec nmMap p t@@ -1076,7 +1114,7 @@ TypeParamInstPos f n -> mk (sh f ++ "_" ++ show n) DefinitionOf x -> case nameInfo x of- Declared m SystemName | m == exprModName -> mk "it"+ Declared m SystemName | m == TopModule exprModName -> mk "it" _ -> using x LenOfCompGen -> mk "n" GeneratorOfListComp -> "seq"@@ -1100,19 +1138,18 @@ ppPrec n t = ppWithNamesPrec IntMap.empty n t instance PP TVarInfo where- ppPrec _ tvinfo = pp (tvarDesc tvinfo) <+> loc+ ppPrec _ tvinfo = hsep $ [pp (tvarDesc tvinfo)] ++ loc where- loc = if rng == emptyRange then empty else "at" <+> pp rng+ loc = if rng == emptyRange then [] else ["at" <+> pp rng] rng = tvarSource tvinfo instance PP ArgDescr where- ppPrec _ ad = which <+> "argument" <+> ofFun+ ppPrec _ ad = hsep ([which, "argument"] ++ ofFun) where which = maybe "function" ordinal (argDescrNumber ad) ofFun = case argDescrFun ad of- Nothing -> empty- Just f -> "of" <+> pp f-+ Nothing -> []+ Just f -> ["of" <+> pp f] instance PP TypeSource where
src/Cryptol/TypeCheck/TypeOf.hs view
@@ -54,8 +54,12 @@ polymorphic = case fastSchemaOf tyenv expr of Forall [] [] ty -> ty- _ -> panic "Cryptol.TypeCheck.TypeOf.fastTypeOf"- [ "unexpected polymorphic type" ]+ s@Forall {} -> panic "Cryptol.TypeCheck.TypeOf.fastTypeOf"+ [ "unexpected polymorphic type in expression:"+ , pretty expr+ , "with schema:"+ , pretty s+ ] fastSchemaOf :: Map Name Schema -> Expr -> Schema fastSchemaOf tyenv expr =@@ -124,13 +128,32 @@ -- | Yields the return type of the selector on the given argument type. typeSelect :: Type -> Selector -> Type++-- Selectors push inside the definition of type aliases typeSelect (TUser _ _ ty) sel = typeSelect ty sel++-- Tuple selector applied to a tuple typeSelect (tIsTuple -> Just ts) (TupleSel i _) | i < length ts = ts !! i++-- Record selector applied to a record typeSelect (TRec fields) (RecordSel n _) | Just ty <- lookupField n fields = ty++-- Record selector applied to a newtype+typeSelect (TNewtype nt args) (RecordSel n _)+ | Just ty <- lookupField n (ntFields nt)+ = plainSubst (listParamSubst (zip (ntParams nt) args)) ty++-- List selector applied to a sequence typeSelect (tIsSeq -> Just (_, a)) ListSel{} = a++-- Tuple selectors and record selectors lift pointwise over sequences typeSelect (tIsSeq -> Just (n, a)) sel@TupleSel{} = tSeq n (typeSelect a sel) typeSelect (tIsSeq -> Just (n, a)) sel@RecordSel{} = tSeq n (typeSelect a sel)++-- Selectors lift pointwise over functions+typeSelect (tIsFun -> Just (a, b)) sel = tFun a (typeSelect b sel)+ typeSelect ty _ = panic "Cryptol.TypeCheck.TypeOf.typeSelect"- [ "cannot apply selector to value of type", render (pp ty) ]+ [ "cannot apply selector to value of type", show (pp ty) ]
src/Cryptol/Utils/Ident.hs view
@@ -7,10 +7,17 @@ -- Portability : portable {-# LANGUAGE DeriveGeneric, OverloadedStrings #-}+{-# LANGUAGE DeriveAnyClass #-} module Cryptol.Utils.Ident ( -- * Module names- ModName+ ModPath(..)+ , apPathRoot+ , modPathCommon+ , topModuleFor+ , modPathSplit++ , ModName , modNameToText , textToModName , modNameChunks@@ -41,6 +48,13 @@ , identText , modParamIdent + -- * Namespaces+ , Namespace(..)+ , allNamespaces++ -- * Original names+ , OrigName(..)+ -- * Identifiers for primitives , PrimIdent(..) , prelPrim@@ -58,7 +72,64 @@ import GHC.Generics (Generic) --- | Module names are just text.+--------------------------------------------------------------------------------++-- | Namespaces for names+data Namespace = NSValue | NSType | NSModule+ deriving (Generic,Show,NFData,Eq,Ord,Enum,Bounded)++allNamespaces :: [Namespace]+allNamespaces = [ minBound .. maxBound ]++-- | Idnetifies a possibly nested module+data ModPath = TopModule ModName+ | Nested ModPath Ident+ deriving (Eq,Ord,Show,Generic,NFData)++apPathRoot :: (ModName -> ModName) -> ModPath -> ModPath+apPathRoot f path =+ case path of+ TopModule m -> TopModule (f m)+ Nested p q -> Nested (apPathRoot f p) q++topModuleFor :: ModPath -> ModName+topModuleFor m =+ case m of+ TopModule x -> x+ Nested p _ -> topModuleFor p++-- | Compute a common prefix between two module paths, if any.+-- This is basically "anti-unification" of the two paths, where we+-- compute the longest common prefix, and the remaining differences for+-- each module.+modPathCommon :: ModPath -> ModPath -> Maybe (ModPath, [Ident], [Ident])+modPathCommon p1 p2+ | top1 == top2 = Just (findCommon (TopModule top1) as bs)+ | otherwise = Nothing+ where+ (top1,as) = modPathSplit p1+ (top2,bs) = modPathSplit p2++ findCommon com xs ys =+ case (xs,ys) of+ (x:xs',y:ys') | x == y -> findCommon (Nested com x) xs' ys'+ _ -> (com, xs, ys)++modPathSplit :: ModPath -> (ModName, [Ident])+modPathSplit p0 = (top,reverse xs)+ where+ (top,xs) = go p0+ go p =+ case p of+ TopModule a -> (a, [])+ Nested b i -> (a, i:bs)+ where (a,bs) = go b+++++--------------------------------------------------------------------------------+-- | Top-level Module names are just text. data ModName = ModName T.Text deriving (Eq,Ord,Show,Generic) @@ -135,6 +206,15 @@ exprModName :: ModName exprModName = packModName ["<expr>"]+++--------------------------------------------------------------------------------+-- | Identifies an entitiy+data OrigName = OrigName+ { ogNamespace :: Namespace+ , ogModule :: ModPath+ , ogName :: Ident+ } deriving (Eq,Ord,Show,Generic,NFData) --------------------------------------------------------------------------------
src/Cryptol/Utils/PP.hs view
@@ -18,23 +18,21 @@ import Control.DeepSeq import Control.Monad (mplus) import Data.Maybe (fromMaybe)-import qualified Data.Semigroup as S import Data.String (IsString(..)) import qualified Data.Text as T+import Data.Void (Void) import GHC.Generics (Generic)-import qualified Text.PrettyPrint as PJ--import Prelude ()-import Prelude.Compat-+import qualified Prettyprinter as PP+import qualified Prettyprinter.Render.String as PP -- | How to pretty print things when evaluating data PPOpts = PPOpts- { useAscii :: Bool- , useBase :: Int- , useInfLength :: Int- , useFPBase :: Int- , useFPFormat :: PPFloatFormat+ { useAscii :: Bool+ , useBase :: Int+ , useInfLength :: Int+ , useFPBase :: Int+ , useFPFormat :: PPFloatFormat+ , useFieldOrder :: FieldOrder } deriving Show @@ -51,11 +49,14 @@ | AutoExponent -- ^ Only show exponent when needed deriving Show +data FieldOrder = DisplayOrder | CanonicalOrder deriving (Bounded, Enum, Eq, Ord, Read, Show) + defaultPPOpts :: PPOpts defaultPPOpts = PPOpts { useAscii = False, useBase = 10, useInfLength = 5 , useFPBase = 16 , useFPFormat = FloatFree AutoExponent+ , useFieldOrder = DisplayOrder } @@ -66,21 +67,21 @@ that the display has no opinion on how this name should be displayed, and some other display should be tried out. -} data NameDisp = EmptyNameDisp- | NameDisp (ModName -> Ident -> Maybe NameFormat)+ | NameDisp (OrigName -> Maybe NameFormat) deriving (Generic, NFData) instance Show NameDisp where show _ = "<NameDisp>" -instance S.Semigroup NameDisp where- NameDisp f <> NameDisp g = NameDisp (\m n -> f m n `mplus` g m n)+instance Semigroup NameDisp where+ NameDisp f <> NameDisp g = NameDisp (\n -> f n `mplus` g n) EmptyNameDisp <> EmptyNameDisp = EmptyNameDisp EmptyNameDisp <> x = x x <> _ = x instance Monoid NameDisp where mempty = EmptyNameDisp- mappend = (S.<>)+ mappend = (<>) data NameFormat = UnQualified | Qualified !ModName@@ -88,21 +89,13 @@ deriving (Show) -- | Never qualify names from this module.-neverQualifyMod :: ModName -> NameDisp-neverQualifyMod mn = NameDisp $ \ mn' _ ->- if mn == mn' then Just UnQualified- else Nothing--alwaysQualify :: NameDisp-alwaysQualify = NameDisp $ \ mn _ -> Just (Qualified mn)+neverQualifyMod :: ModPath -> NameDisp+neverQualifyMod mn = NameDisp $ \n ->+ if ogModule n == mn then Just UnQualified else Nothing neverQualify :: NameDisp-neverQualify = NameDisp $ \ _ _ -> Just UnQualified+neverQualify = NameDisp $ \ _ -> Just UnQualified -fmtModName :: ModName -> NameFormat -> T.Text-fmtModName _ UnQualified = T.empty-fmtModName _ (Qualified mn) = modNameToText mn-fmtModName mn NotInScope = modNameToText mn -- | Compose two naming environments, preferring names from the left -- environment.@@ -111,9 +104,9 @@ -- | Get the format for a name. When 'Nothing' is returned, the name is not -- currently in scope.-getNameFormat :: ModName -> Ident -> NameDisp -> NameFormat-getNameFormat m i (NameDisp f) = fromMaybe NotInScope (f m i)-getNameFormat _ _ EmptyNameDisp = NotInScope+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@@ -126,29 +119,27 @@ -- Documents ------------------------------------------------------------------- -newtype Doc = Doc (NameDisp -> PJ.Doc) deriving (Generic, NFData)+newtype Doc = Doc (NameDisp -> PP.Doc Void) deriving (Generic, NFData) -instance S.Semigroup Doc where- (<>) = liftPJ2 (PJ.<>)+instance Semigroup Doc where+ (<>) = liftPP2 (<>) instance Monoid Doc where- mempty = liftPJ PJ.empty- mappend = (S.<>)+ mempty = liftPP mempty+ mappend = (<>) -runDoc :: NameDisp -> Doc -> PJ.Doc+runDoc :: NameDisp -> Doc -> PP.Doc Void runDoc names (Doc f) = f names instance Show Doc where- show d = show (runDoc mempty d)+ show d = PP.renderString (PP.layoutPretty opts (runDoc mempty d))+ where opts = PP.defaultLayoutOptions{ PP.layoutPageWidth = PP.AvailablePerLine 100 0.666 } instance IsString Doc where fromString = text -render :: Doc -> String-render d = PJ.render (runDoc mempty d)- renderOneLine :: Doc -> String-renderOneLine d = PJ.renderStyle (PJ.style { PJ.mode = PJ.OneLineMode }) (runDoc mempty d)+renderOneLine d = PP.renderString (PP.layoutCompact (runDoc mempty d)) class PP a where ppPrec :: Int -> a -> Doc@@ -163,6 +154,11 @@ -- | Print a name as an infix operator: @a + b@ ppInfixName :: a -> Doc +instance PPName ModName where+ ppNameFixity _ = Nothing+ ppPrefixName = pp+ ppInfixName = pp+ pp :: PP a => a -> Doc pp = ppPrec 0 @@ -170,7 +166,7 @@ pretty = show . pp optParens :: Bool -> Doc -> Doc-optParens b body | b = parens body+optParens b body | b = nest 1 (parens body) | otherwise = body @@ -182,10 +178,6 @@ , ieFixity :: Fixity -- ^ operator fixity } -commaSep :: [Doc] -> Doc-commaSep = fsep . punctuate comma-- -- | Pretty print an infix expression of some sort. ppInfix :: (PP thing, PP op) => Int -- ^ Non-infix leaves are printed with this precedence@@ -227,94 +219,123 @@ -- Wrapped Combinators --------------------------------------------------------- -liftPJ :: PJ.Doc -> Doc-liftPJ d = Doc (const d)+liftPP :: PP.Doc Void -> Doc+liftPP d = Doc (const d) -liftPJ1 :: (PJ.Doc -> PJ.Doc) -> Doc -> Doc-liftPJ1 f (Doc d) = Doc (\env -> f (d env))+liftPP1 :: (PP.Doc Void -> PP.Doc Void) -> Doc -> Doc+liftPP1 f (Doc d) = Doc (\env -> f (d env)) -liftPJ2 :: (PJ.Doc -> PJ.Doc -> PJ.Doc) -> (Doc -> Doc -> Doc)-liftPJ2 f (Doc a) (Doc b) = Doc (\e -> f (a e) (b e))+liftPP2 :: (PP.Doc Void -> PP.Doc Void -> PP.Doc Void) -> (Doc -> Doc -> Doc)+liftPP2 f (Doc a) (Doc b) = Doc (\e -> f (a e) (b e)) -liftSep :: ([PJ.Doc] -> PJ.Doc) -> ([Doc] -> Doc)+liftSep :: ([PP.Doc Void] -> PP.Doc Void) -> ([Doc] -> Doc) liftSep f ds = Doc (\e -> f [ d e | Doc d <- ds ]) -infixl 6 <.>, <+>+infixl 6 <.>, <+>, </> (<.>) :: Doc -> Doc -> Doc-(<.>) = liftPJ2 (PJ.<>)+(<.>) = liftPP2 (PP.<>) (<+>) :: Doc -> Doc -> Doc-(<+>) = liftPJ2 (PJ.<+>)+(<+>) = liftPP2 (PP.<+>) +(</>) :: Doc -> Doc -> Doc+Doc x </> Doc y = Doc (\e -> x e <> PP.softline <> y e)+ infixl 5 $$ ($$) :: Doc -> Doc -> Doc-($$) = liftPJ2 (PJ.$$)+($$) x y = vsep [x,y] sep :: [Doc] -> Doc-sep = liftSep PJ.sep+sep = liftSep PP.sep fsep :: [Doc] -> Doc-fsep = liftSep PJ.fsep+fsep = liftSep PP.fillSep hsep :: [Doc] -> Doc-hsep = liftSep PJ.hsep+hsep = liftSep PP.hsep hcat :: [Doc] -> Doc-hcat = liftSep PJ.hcat+hcat = liftSep PP.hcat vcat :: [Doc] -> Doc-vcat = liftSep PJ.vcat+vcat = liftSep PP.vcat +vsep :: [Doc] -> Doc+vsep = liftSep PP.vsep++group :: Doc -> Doc+group = liftPP1 PP.group++-- NB, this is the semantics of "hang" as defined+-- by the HugesPJ printer, not the "hang" from prettyprinter,+-- which is subtly different. hang :: Doc -> Int -> Doc -> Doc-hang (Doc p) i (Doc q) = Doc (\e -> PJ.hang (p e) i (q e))+hang (Doc p) i (Doc q) = Doc (\e -> PP.hang i (PP.vsep [p e, q e])) nest :: Int -> Doc -> Doc-nest n = liftPJ1 (PJ.nest n)+nest n = liftPP1 (PP.nest n) +indent :: Int -> Doc -> Doc+indent n = liftPP1 (PP.indent n)++align :: Doc -> Doc+align = liftPP1 PP.align+ parens :: Doc -> Doc-parens = liftPJ1 PJ.parens+parens = liftPP1 PP.parens braces :: Doc -> Doc-braces = liftPJ1 PJ.braces+braces = liftPP1 PP.braces brackets :: Doc -> Doc-brackets = liftPJ1 PJ.brackets+brackets = liftPP1 PP.brackets quotes :: Doc -> Doc-quotes = liftPJ1 PJ.quotes+quotes = liftPP1 PP.squotes -backticks :: Doc -> Doc-backticks d = hcat [ "`", d, "`" ]+commaSep :: [Doc] -> Doc+commaSep xs = Doc (\e -> PP.sep (PP.punctuate PP.comma [ d e | Doc d <- xs ])) -punctuate :: Doc -> [Doc] -> [Doc]-punctuate p = go+-- | Print a comma-separated list. Lay out each item on a single line+-- if it will fit. If an item requires multiple lines, then start it+-- on its own line.+commaSepFill :: [Doc] -> Doc+commaSepFill xs = Doc (\e -> fillSep (PP.punctuate PP.comma [ d e | Doc d <- xs ])) where- go (d:ds) | null ds = [d]- | otherwise = d <.> p : go ds- go [] = []+ fillSep [] = mempty+ fillSep (d0 : ds) = foldl (\a d -> a <> PP.group (PP.line <> d)) d0 ds +ppList :: [Doc] -> Doc+ppList xs = group (nest 1 (brackets (commaSepFill xs)))++ppTuple :: [Doc] -> Doc+ppTuple xs = group (nest 1 (parens (commaSep xs)))++ppRecord :: [Doc] -> Doc+ppRecord xs = group (nest 1 (braces (commaSep xs)))++backticks :: Doc -> Doc+backticks d = hcat [ "`", d, "`" ]+ text :: String -> Doc-text s = liftPJ (PJ.text s)+text s = liftPP (PP.pretty s) char :: Char -> Doc-char c = liftPJ (PJ.char c)+char c = liftPP (PP.pretty c) integer :: Integer -> Doc-integer i = liftPJ (PJ.integer i)+integer i = liftPP (PP.pretty i) int :: Int -> Doc-int i = liftPJ (PJ.int i)+int i = liftPP (PP.pretty i) comma :: Doc-comma = liftPJ PJ.comma--empty :: Doc-empty = liftPJ PJ.empty+comma = liftPP PP.comma colon :: Doc-colon = liftPJ PJ.colon+colon = liftPP PP.colon instance PP T.Text where ppPrec _ str = text (T.unpack str)@@ -325,6 +346,7 @@ instance PP ModName where ppPrec _ = text . T.unpack . modNameToText + instance PP Assoc where ppPrec _ LeftAssoc = text "left-associative" ppPrec _ RightAssoc = text "right-associative"@@ -333,3 +355,31 @@ instance PP Fixity where ppPrec _ (Fixity assoc level) = text "precedence" <+> int level <.> comma <+> pp assoc++instance PP ModPath where+ ppPrec _ p =+ case p of+ TopModule m -> pp m+ Nested q t -> pp q <.> "::" <.> pp t++instance PP OrigName where+ ppPrec _ og =+ withNameDisp $ \disp ->+ case getNameFormat og disp of+ UnQualified -> pp (ogName og)+ Qualified m -> ppQual (TopModule m) (pp (ogName og))+ NotInScope -> ppQual (ogModule og) (pp (ogName og))+ where+ ppQual mo x =+ case mo of+ TopModule m+ | m == exprModName -> x+ | otherwise -> pp m <.> "::" <.> x+ Nested m y -> ppQual m (pp y <.> "::" <.> x)++instance PP Namespace where+ ppPrec _ ns =+ case ns of+ NSValue -> "/*value*/"+ NSType -> "/*type*/"+ NSModule -> "/*module*/"