packages feed

cryptol 2.10.0 → 2.11.0

raw patch · 81 files changed

+3775/−2648 lines, 81 filesdep +extradep +optparse-applicativedep +temporarydep ~basedep ~containersdep ~directorynew-component:exe:check-exercisesPVP ok

version bump matches the API change (PVP)

Dependencies added: extra, optparse-applicative, temporary

Dependency ranges changed: base, containers, directory, filepath, libBF, mtl, process, sbv, text, what4

API changes (from Hackage documentation)

- Cryptol.Backend: ppBit :: Backend sym => sym -> SBit sym -> Doc
- Cryptol.Backend: ppFloat :: Backend sym => sym -> PPOpts -> SFloat sym -> Doc
- Cryptol.Backend: ppInteger :: Backend sym => sym -> PPOpts -> SInteger sym -> Doc
- Cryptol.Backend: ppRational :: Backend sym => sym -> PPOpts -> SRational sym -> Doc
- Cryptol.Backend: ppWord :: Backend sym => sym -> PPOpts -> SWord sym -> Doc
- Cryptol.Backend.FloatHelpers: floatFromBits' :: Integer -> Integer -> Integer -> BigFloat
- Cryptol.Backend.Monad: AutoExponent :: PPFloatExp
- Cryptol.Backend.Monad: EvalOpts :: Logger -> PPOpts -> EvalOpts
- Cryptol.Backend.Monad: FloatFixed :: Int -> PPFloatExp -> PPFloatFormat
- Cryptol.Backend.Monad: FloatFrac :: Int -> PPFloatFormat
- Cryptol.Backend.Monad: FloatFree :: PPFloatExp -> PPFloatFormat
- Cryptol.Backend.Monad: ForceExponent :: PPFloatExp
- Cryptol.Backend.Monad: PPOpts :: Bool -> Int -> Int -> Int -> PPFloatFormat -> PPOpts
- Cryptol.Backend.Monad: TypeCannotBeDemoted :: Type -> EvalError
- Cryptol.Backend.Monad: [evalLogger] :: EvalOpts -> Logger
- Cryptol.Backend.Monad: [evalPPOpts] :: EvalOpts -> PPOpts
- Cryptol.Backend.Monad: [useAscii] :: PPOpts -> Bool
- Cryptol.Backend.Monad: [useBase] :: PPOpts -> Int
- Cryptol.Backend.Monad: [useFPBase] :: PPOpts -> Int
- Cryptol.Backend.Monad: [useFPFormat] :: PPOpts -> PPFloatFormat
- Cryptol.Backend.Monad: [useInfLength] :: PPOpts -> Int
- Cryptol.Backend.Monad: asciiMode :: PPOpts -> Integer -> Bool
- Cryptol.Backend.Monad: data EvalOpts
- Cryptol.Backend.Monad: data PPFloatExp
- Cryptol.Backend.Monad: data PPFloatFormat
- Cryptol.Backend.Monad: data PPOpts
- Cryptol.Backend.Monad: defaultPPOpts :: PPOpts
- Cryptol.Backend.Monad: instance Control.Monad.Fail.MonadFail Cryptol.Backend.Monad.Eval
- Cryptol.Backend.Monad: instance Control.Monad.Fix.MonadFix Cryptol.Backend.Monad.Eval
- Cryptol.Backend.Monad: instance GHC.Exception.Type.Exception Cryptol.Backend.Monad.EvalError
- Cryptol.Backend.Monad: typeCannotBeDemoted :: Type -> a
- Cryptol.Backend.What4.SFloat: FPTypeError :: Some BaseTypeRepr -> Some BaseTypeRepr -> FPTypeError
- Cryptol.Backend.What4.SFloat: UnsupportedFloat :: String -> Integer -> UnsupportedFloat
- Cryptol.Backend.What4.SFloat: [SFloat] :: IsExpr (SymExpr sym) => SymFloat sym fpp -> SFloat sym
- Cryptol.Backend.What4.SFloat: [exponentBits, precisionBits] :: UnsupportedFloat -> Integer
- Cryptol.Backend.What4.SFloat: [fpActual] :: FPTypeError -> Some BaseTypeRepr
- Cryptol.Backend.What4.SFloat: [fpExpected] :: FPTypeError -> Some BaseTypeRepr
- Cryptol.Backend.What4.SFloat: [fpWho] :: UnsupportedFloat -> String
- Cryptol.Backend.What4.SFloat: data FPTypeError
- Cryptol.Backend.What4.SFloat: data SFloat sym
- Cryptol.Backend.What4.SFloat: data UnsupportedFloat
- Cryptol.Backend.What4.SFloat: fpAdd :: IsExprBuilder sym => SFloatBinArith sym
- Cryptol.Backend.What4.SFloat: fpDiv :: IsExprBuilder sym => SFloatBinArith sym
- Cryptol.Backend.What4.SFloat: fpEq :: IsExprBuilder sym => SFloatRel sym
- Cryptol.Backend.What4.SFloat: fpEqIEEE :: IsExprBuilder sym => SFloatRel sym
- Cryptol.Backend.What4.SFloat: fpFresh :: IsSymExprBuilder sym => sym -> Integer -> Integer -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpFromBinary :: IsExprBuilder sym => sym -> Integer -> Integer -> SWord sym -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpFromInteger :: IsExprBuilder sym => sym -> Integer -> Integer -> RoundingMode -> SymInteger sym -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpFromRational :: IsExprBuilder sym => sym -> Integer -> Integer -> RoundingMode -> SymInteger sym -> SymInteger sym -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpFromRationalLit :: IsExprBuilder sym => sym -> Integer -> Integer -> Rational -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpFromReal :: IsExprBuilder sym => sym -> Integer -> Integer -> RoundingMode -> SymReal sym -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpGtIEEE :: IsExprBuilder sym => SFloatRel sym
- Cryptol.Backend.What4.SFloat: fpIsInf :: IsExprBuilder sym => sym -> SFloat sym -> IO (Pred sym)
- Cryptol.Backend.What4.SFloat: fpIsNaN :: IsExprBuilder sym => sym -> SFloat sym -> IO (Pred sym)
- Cryptol.Backend.What4.SFloat: fpLtIEEE :: IsExprBuilder sym => SFloatRel sym
- Cryptol.Backend.What4.SFloat: fpMul :: IsExprBuilder sym => SFloatBinArith sym
- Cryptol.Backend.What4.SFloat: fpNaN :: IsExprBuilder sym => sym -> Integer -> Integer -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpNeg :: IsExprBuilder sym => sym -> SFloat sym -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpPosInf :: IsExprBuilder sym => sym -> Integer -> Integer -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpRepr :: Integer -> Integer -> Maybe (Some FloatPrecisionRepr)
- Cryptol.Backend.What4.SFloat: fpReprOf :: IsExpr (SymExpr sym) => sym -> SymFloat sym fpp -> FloatPrecisionRepr fpp
- Cryptol.Backend.What4.SFloat: fpRound :: IsExprBuilder sym => sym -> RoundingMode -> SFloat sym -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: fpSize :: SFloat sym -> (Integer, Integer)
- Cryptol.Backend.What4.SFloat: fpSub :: IsExprBuilder sym => SFloatBinArith sym
- Cryptol.Backend.What4.SFloat: fpToBinary :: IsExprBuilder sym => sym -> SFloat sym -> IO (SWord sym)
- Cryptol.Backend.What4.SFloat: fpToRational :: IsSymExprBuilder sym => sym -> SFloat sym -> IO (Pred sym, SymInteger sym, SymInteger sym)
- Cryptol.Backend.What4.SFloat: fpToReal :: IsExprBuilder sym => sym -> SFloat sym -> IO (SymReal sym)
- Cryptol.Backend.What4.SFloat: instance GHC.Exception.Type.Exception Cryptol.Backend.What4.SFloat.FPTypeError
- Cryptol.Backend.What4.SFloat: instance GHC.Exception.Type.Exception Cryptol.Backend.What4.SFloat.UnsupportedFloat
- Cryptol.Backend.What4.SFloat: instance GHC.Show.Show Cryptol.Backend.What4.SFloat.FPTypeError
- Cryptol.Backend.What4.SFloat: instance GHC.Show.Show Cryptol.Backend.What4.SFloat.UnsupportedFloat
- Cryptol.Backend.What4.SFloat: type SFloatBinArith sym = sym -> RoundingMode -> SFloat sym -> SFloat sym -> IO (SFloat sym)
- Cryptol.Backend.What4.SFloat: type SFloatRel sym = sym -> SFloat sym -> SFloat sym -> IO (Pred sym)
- Cryptol.Eval: TypeCannotBeDemoted :: Type -> EvalError
- Cryptol.Eval.Type: type TypeEnv = IntMap (Either Nat' TValue)
- Cryptol.Eval.Value: ppBit :: Backend sym => sym -> SBit sym -> Doc
- Cryptol.Eval.Value: ppFloat :: Backend sym => sym -> PPOpts -> SFloat sym -> Doc
- Cryptol.Eval.Value: ppInteger :: Backend sym => sym -> PPOpts -> SInteger sym -> Doc
- Cryptol.Eval.Value: ppWord :: Backend sym => sym -> PPOpts -> SWord sym -> Doc
- Cryptol.Eval.Value: wlam :: Backend sym => sym -> (SWord sym -> SEval sym (GenValue sym)) -> GenValue sym
- Cryptol.Eval.What4: floatPrims :: IsSymExprBuilder sym => What4 sym -> Map PrimIdent (Value sym)
- Cryptol.ModuleSystem.Name: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Cryptol.ModuleSystem.Name.SupplyT m)
- Cryptol.Testing.Random: TestReport :: TestResult -> String -> Integer -> Maybe Integer -> TestReport
- Cryptol.Testing.Random: [reportProp] :: TestReport -> String
- Cryptol.Testing.Random: [reportResult] :: TestReport -> TestResult
- Cryptol.Testing.Random: [reportTestsPossible] :: TestReport -> Maybe Integer
- Cryptol.Testing.Random: [reportTestsRun] :: TestReport -> Integer
- Cryptol.Testing.Random: data TestReport
- Cryptol.TypeCheck.Monad: instance GHC.Show.Show Cryptol.TypeCheck.Monad.InferInput
- Cryptol.TypeCheck.TCon: TCNewtype :: UserTC -> TC
- Cryptol.TypeCheck.Type: TPOther :: Maybe Name -> TPFlavor
- Cryptol.TypeCheck.Type: newtypeTyCon :: Newtype -> TCon
+ Cryptol.Backend: fpAbs :: Backend sym => sym -> SFloat sym -> SEval sym (SFloat sym)
+ Cryptol.Backend: fpAsLit :: Backend sym => sym -> SFloat sym -> Maybe BF
+ Cryptol.Backend: fpFMA :: Backend sym => sym -> SWord sym -> SFloat sym -> SFloat sym -> SFloat sym -> SEval sym (SFloat sym)
+ Cryptol.Backend: fpFromBits :: Backend sym => sym -> Integer -> Integer -> SWord sym -> SEval sym (SFloat sym)
+ Cryptol.Backend: fpFromRational :: Backend sym => sym -> Integer -> Integer -> SWord sym -> SRational sym -> SEval sym (SFloat sym)
+ Cryptol.Backend: fpIsInf :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Backend: fpIsNaN :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Backend: fpIsNeg :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Backend: fpIsNorm :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Backend: fpIsSubnorm :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Backend: fpIsZero :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Backend: fpNaN :: Backend sym => sym -> Integer -> Integer -> SEval sym (SFloat sym)
+ Cryptol.Backend: fpPosInf :: Backend sym => sym -> Integer -> Integer -> SEval sym (SFloat sym)
+ Cryptol.Backend: fpSqrt :: Backend sym => sym -> SWord sym -> SFloat sym -> SEval sym (SFloat sym)
+ Cryptol.Backend: fpToBits :: Backend sym => sym -> SFloat sym -> SEval sym (SWord sym)
+ Cryptol.Backend: fpToRational :: Backend sym => sym -> SFloat sym -> SEval sym (SRational sym)
+ Cryptol.Backend: iteFloat :: Backend sym => sym -> SBit sym -> SFloat sym -> SFloat sym -> SEval sym (SFloat sym)
+ Cryptol.Backend: sGetCallStack :: Backend sym => sym -> SEval sym CallStack
+ Cryptol.Backend: sModifyCallStack :: Backend sym => sym -> (CallStack -> CallStack) -> SEval sym a -> SEval sym a
+ Cryptol.Backend: sPushFrame :: Backend sym => sym -> Name -> Range -> SEval sym a -> SEval sym a
+ Cryptol.Backend: sWithCallStack :: Backend sym => sym -> CallStack -> SEval sym a -> SEval sym a
+ Cryptol.Backend.Monad: EvalErrorEx :: CallStack -> EvalError -> EvalErrorEx
+ Cryptol.Backend.Monad: combineCallStacks :: CallStack -> CallStack -> CallStack
+ Cryptol.Backend.Monad: data EvalErrorEx
+ Cryptol.Backend.Monad: data WordTooWide
+ Cryptol.Backend.Monad: displayCallStack :: CallStack -> Doc
+ Cryptol.Backend.Monad: getCallStack :: Eval CallStack
+ Cryptol.Backend.Monad: instance Cryptol.Utils.PP.PP Cryptol.Backend.Monad.EvalErrorEx
+ Cryptol.Backend.Monad: instance Cryptol.Utils.PP.PP Cryptol.Backend.Monad.WordTooWide
+ Cryptol.Backend.Monad: instance GHC.Exception.Type.Exception Cryptol.Backend.Monad.EvalErrorEx
+ Cryptol.Backend.Monad: instance GHC.Exception.Type.Exception Cryptol.Backend.Monad.WordTooWide
+ Cryptol.Backend.Monad: instance GHC.Show.Show Cryptol.Backend.Monad.EvalErrorEx
+ Cryptol.Backend.Monad: instance GHC.Show.Show Cryptol.Backend.Monad.WordTooWide
+ Cryptol.Backend.Monad: modifyCallStack :: (CallStack -> CallStack) -> Eval a -> Eval a
+ Cryptol.Backend.Monad: pushCallFrame :: Name -> Range -> CallStack -> CallStack
+ Cryptol.Backend.Monad: type CallStack = Seq (Name, Range)
+ Cryptol.Backend.Monad: withCallStack :: CallStack -> Eval a -> Eval a
+ Cryptol.Eval: EvalErrorEx :: CallStack -> EvalError -> EvalErrorEx
+ Cryptol.Eval: data EvalErrorEx
+ Cryptol.Eval: data WordTooWide
+ Cryptol.Eval: evalNewtypeDecls :: EvalPrims sym => sym -> Map Name Newtype -> GenEvalEnv sym -> SEval sym (GenEvalEnv sym)
+ Cryptol.Eval.Generic: fpConst :: Backend sym => (Integer -> Integer -> SEval sym (SFloat sym)) -> Prim sym
+ Cryptol.Eval.Generic: fromToLessThanV :: Backend sym => sym -> Prim sym
+ Cryptol.Eval.Generic: genericFloatTable :: Backend sym => sym -> Map PrimIdent (Prim sym)
+ Cryptol.Eval.Generic: genericPrimTable :: Backend sym => sym -> IO EvalOpts -> Map PrimIdent (Prim sym)
+ Cryptol.Eval.Prims: PFinPoly :: (Integer -> Prim sym) -> Prim sym
+ Cryptol.Eval.Prims: PFloatFun :: (SFloat sym -> Prim sym) -> Prim sym
+ Cryptol.Eval.Prims: PFun :: (SEval sym (GenValue sym) -> Prim sym) -> Prim sym
+ Cryptol.Eval.Prims: PNumPoly :: (Nat' -> Prim sym) -> Prim sym
+ Cryptol.Eval.Prims: PPrim :: SEval sym (GenValue sym) -> Prim sym
+ Cryptol.Eval.Prims: PStrict :: (GenValue sym -> Prim sym) -> Prim sym
+ Cryptol.Eval.Prims: PTyPoly :: (TValue -> Prim sym) -> Prim sym
+ Cryptol.Eval.Prims: PVal :: GenValue sym -> Prim sym
+ Cryptol.Eval.Prims: PWordFun :: (SWord sym -> Prim sym) -> Prim sym
+ Cryptol.Eval.Prims: data Prim sym
+ Cryptol.Eval.Prims: evalPrim :: Backend sym => sym -> Name -> Prim sym -> SEval sym (GenValue sym)
+ Cryptol.Eval.Type: TVNewtype :: Newtype -> [Either Nat' TValue] -> RecordMap Ident TValue -> TValue
+ Cryptol.Eval.Type: TypeEnv :: IntMap (Either Nat' TValue) -> TypeEnv
+ Cryptol.Eval.Type: [envTypeMap] :: TypeEnv -> IntMap (Either Nat' TValue)
+ Cryptol.Eval.Type: bindTypeVar :: TVar -> Either Nat' TValue -> TypeEnv -> TypeEnv
+ Cryptol.Eval.Type: evalNewtypeBody :: TypeEnv -> Newtype -> [Either Nat' TValue] -> RecordMap Ident TValue
+ Cryptol.Eval.Type: instance GHC.Base.Monoid Cryptol.Eval.Type.TypeEnv
+ Cryptol.Eval.Type: instance GHC.Base.Semigroup Cryptol.Eval.Type.TypeEnv
+ Cryptol.Eval.Type: instance GHC.Classes.Eq Cryptol.Eval.Type.TValue
+ Cryptol.Eval.Type: lookupTypeVar :: TVar -> TypeEnv -> Maybe (Either Nat' TValue)
+ Cryptol.Eval.Type: newtype TypeEnv
+ Cryptol.Eval.Type: tNumTy :: Nat' -> Type
+ Cryptol.Eval.Type: tNumValTy :: Either Nat' TValue -> Type
+ Cryptol.Eval.Value: EvalOpts :: Logger -> PPOpts -> EvalOpts
+ Cryptol.Eval.Value: [evalLogger] :: EvalOpts -> Logger
+ Cryptol.Eval.Value: [evalPPOpts] :: EvalOpts -> PPOpts
+ Cryptol.Eval.Value: data EvalOpts
+ Cryptol.Eval.Value: fpAbs :: Backend sym => sym -> SFloat sym -> SEval sym (SFloat sym)
+ Cryptol.Eval.Value: fpAsLit :: Backend sym => sym -> SFloat sym -> Maybe BF
+ Cryptol.Eval.Value: fpFMA :: Backend sym => sym -> SWord sym -> SFloat sym -> SFloat sym -> SFloat sym -> SEval sym (SFloat sym)
+ Cryptol.Eval.Value: fpFromBits :: Backend sym => sym -> Integer -> Integer -> SWord sym -> SEval sym (SFloat sym)
+ Cryptol.Eval.Value: fpFromRational :: Backend sym => sym -> Integer -> Integer -> SWord sym -> SRational sym -> SEval sym (SFloat sym)
+ Cryptol.Eval.Value: fpIsInf :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Eval.Value: fpIsNaN :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Eval.Value: fpIsNeg :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Eval.Value: fpIsNorm :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Eval.Value: fpIsSubnorm :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Eval.Value: fpIsZero :: Backend sym => sym -> SFloat sym -> SEval sym (SBit sym)
+ Cryptol.Eval.Value: fpNaN :: Backend sym => sym -> Integer -> Integer -> SEval sym (SFloat sym)
+ Cryptol.Eval.Value: fpPosInf :: Backend sym => sym -> Integer -> Integer -> SEval sym (SFloat sym)
+ Cryptol.Eval.Value: fpSqrt :: Backend sym => sym -> SWord sym -> SFloat sym -> SEval sym (SFloat sym)
+ Cryptol.Eval.Value: fpToBits :: Backend sym => sym -> SFloat sym -> SEval sym (SWord sym)
+ Cryptol.Eval.Value: fpToRational :: Backend sym => sym -> SFloat sym -> SEval sym (SRational sym)
+ Cryptol.Eval.Value: iteFloat :: Backend sym => sym -> SBit sym -> SFloat sym -> SFloat sym -> SEval sym (SFloat sym)
+ Cryptol.Eval.Value: sGetCallStack :: Backend sym => sym -> SEval sym CallStack
+ Cryptol.Eval.Value: sModifyCallStack :: Backend sym => sym -> (CallStack -> CallStack) -> SEval sym a -> SEval sym a
+ Cryptol.Eval.Value: sPushFrame :: Backend sym => sym -> Name -> Range -> SEval sym a -> SEval sym a
+ Cryptol.Eval.Value: sWithCallStack :: Backend sym => sym -> CallStack -> SEval sym a -> SEval sym a
+ Cryptol.ModuleSystem: ModuleInput :: Bool -> m EvalOpts -> (FilePath -> m ByteString) -> ModuleEnv -> Solver -> ModuleInput m
+ Cryptol.ModuleSystem: [minpByteReader] :: ModuleInput m -> FilePath -> m ByteString
+ Cryptol.ModuleSystem: [minpCallStacks] :: ModuleInput m -> Bool
+ Cryptol.ModuleSystem: [minpEvalOpts] :: ModuleInput m -> m EvalOpts
+ Cryptol.ModuleSystem: [minpModuleEnv] :: ModuleInput m -> ModuleEnv
+ Cryptol.ModuleSystem: [minpTCSolver] :: ModuleInput m -> Solver
+ Cryptol.ModuleSystem: data ModuleInput m
+ Cryptol.ModuleSystem.Env: loadedNewtypes :: ModuleEnv -> Map Name IfaceNewtype
+ Cryptol.ModuleSystem.Monad: ModuleInput :: Bool -> m EvalOpts -> (FilePath -> m ByteString) -> ModuleEnv -> Solver -> ModuleInput m
+ Cryptol.ModuleSystem.Monad: [minpByteReader] :: ModuleInput m -> FilePath -> m ByteString
+ Cryptol.ModuleSystem.Monad: [minpCallStacks] :: ModuleInput m -> Bool
+ Cryptol.ModuleSystem.Monad: [minpEvalOpts] :: ModuleInput m -> m EvalOpts
+ Cryptol.ModuleSystem.Monad: [minpModuleEnv] :: ModuleInput m -> ModuleEnv
+ Cryptol.ModuleSystem.Monad: [minpTCSolver] :: ModuleInput m -> Solver
+ Cryptol.ModuleSystem.Monad: [roCallStacks] :: RO m -> Bool
+ Cryptol.ModuleSystem.Monad: [roTCSolver] :: RO m -> Solver
+ Cryptol.ModuleSystem.Monad: data ModuleInput m
+ Cryptol.ModuleSystem.Monad: getCallStacks :: Monad m => ModuleT m Bool
+ Cryptol.ModuleSystem.Monad: getEvalOptsAction :: ModuleM (IO EvalOpts)
+ Cryptol.ModuleSystem.Monad: getNewtypes :: ModuleM (Map Name Newtype)
+ Cryptol.ModuleSystem.Monad: getTCSolver :: Monad m => ModuleT m Solver
+ Cryptol.ModuleSystem.Renamer: instance Cryptol.ModuleSystem.Renamer.Rename Cryptol.Parser.AST.FunDesc
+ Cryptol.Parser: [cfgStart] :: Config -> !Position
+ Cryptol.Parser.AST: EFromToLessThan :: Type n -> Type n -> Maybe (Type n) -> Expr n
+ Cryptol.Parser.AST: FunDesc :: Maybe n -> Int -> FunDesc n
+ Cryptol.Parser.AST: [funDescrArgOffset] :: FunDesc n -> Int
+ Cryptol.Parser.AST: [funDescrName] :: FunDesc n -> Maybe n
+ Cryptol.Parser.AST: data FunDesc n
+ Cryptol.Parser.AST: emptyFunDesc :: FunDesc n
+ Cryptol.Parser.AST: instance Control.DeepSeq.NFData n => Control.DeepSeq.NFData (Cryptol.Parser.AST.FunDesc n)
+ Cryptol.Parser.AST: instance GHC.Base.Functor Cryptol.Parser.AST.FunDesc
+ Cryptol.Parser.AST: instance GHC.Classes.Eq n => GHC.Classes.Eq (Cryptol.Parser.AST.FunDesc n)
+ Cryptol.Parser.AST: instance GHC.Generics.Generic (Cryptol.Parser.AST.FunDesc n)
+ Cryptol.Parser.AST: instance GHC.Show.Show n => GHC.Show.Show (Cryptol.Parser.AST.FunDesc n)
+ Cryptol.Parser.Lexer: DotDotLt :: TokenSym
+ Cryptol.Parser.Lexer: Lt :: TokenSym
+ Cryptol.Parser.Lexer: [cfgStart] :: Config -> !Position
+ Cryptol.Parser.Position: rCombMaybe :: Maybe Range -> Maybe Range -> Maybe Range
+ Cryptol.REPL.Command: TestReport :: Doc -> TestResult -> Integer -> Maybe Integer -> TestReport
+ Cryptol.REPL.Command: [reportExpr] :: TestReport -> Doc
+ Cryptol.REPL.Command: [reportResult] :: TestReport -> TestResult
+ Cryptol.REPL.Command: [reportTestsPossible] :: TestReport -> Maybe Integer
+ Cryptol.REPL.Command: [reportTestsRun] :: TestReport -> Integer
+ Cryptol.REPL.Command: data TestReport
+ Cryptol.REPL.Command: qcExpr :: QCMode -> Doc -> Expr -> Schema -> REPL TestReport
+ Cryptol.REPL.Monad: TooWide :: WordTooWide -> REPLException
+ Cryptol.REPL.Monad: [optAliases] :: OptionDescr -> [String]
+ Cryptol.REPL.Monad: getCallStacks :: REPL Bool
+ Cryptol.REPL.Monad: getEvalOptsAction :: REPL (IO EvalOpts)
+ Cryptol.REPL.Monad: getPPValOpts :: REPL PPOpts
+ Cryptol.REPL.Monad: userOptionsWithAliases :: OptionMap
+ Cryptol.Symbolic: FTNewtype :: Newtype -> [Either Nat' TValue] -> RecordMap Ident FinType -> FinType
+ Cryptol.TypeCheck: BadParameterKind :: TParam -> Kind -> Error
+ Cryptol.TypeCheck: BareTypeApp :: Error
+ Cryptol.TypeCheck: [inpCallStacks] :: InferInput -> Bool
+ Cryptol.TypeCheck: [inpSolver] :: InferInput -> Solver
+ Cryptol.TypeCheck.AST: ELocated :: Range -> Expr -> Expr
+ Cryptol.TypeCheck.AST: instance Cryptol.Parser.Position.HasLoc Cryptol.TypeCheck.AST.Expr
+ Cryptol.TypeCheck.Error: BadParameterKind :: TParam -> Kind -> Error
+ Cryptol.TypeCheck.Error: BareTypeApp :: Error
+ Cryptol.TypeCheck.InferTypes: [literalLessThanGoals] :: Goals -> Map TVar LitGoal
+ Cryptol.TypeCheck.InferTypes: goalToLitLessThanGoal :: Goal -> Maybe (TVar, LitGoal)
+ Cryptol.TypeCheck.InferTypes: litLessThanGoalToGoal :: (TVar, LitGoal) -> Goal
+ Cryptol.TypeCheck.Monad: [iCallStacks] :: RO -> Bool
+ Cryptol.TypeCheck.Monad: [inpCallStacks] :: InferInput -> Bool
+ Cryptol.TypeCheck.Monad: [inpSolver] :: InferInput -> Solver
+ Cryptol.TypeCheck.Monad: checkParamKind :: TParam -> TPFlavor -> Kind -> InferM ()
+ Cryptol.TypeCheck.Monad: getCallStacks :: InferM Bool
+ Cryptol.TypeCheck.Solver.Class: solveLiteralLessThanInst :: Type -> Type -> Solved
+ Cryptol.TypeCheck.Solver.SMT: startSolver :: SolverConfig -> IO Solver
+ Cryptol.TypeCheck.Solver.SMT: stopSolver :: Solver -> IO ()
+ Cryptol.TypeCheck.TCon: PLiteralLessThan :: PC
+ Cryptol.TypeCheck.Type: TNewtype :: !Newtype -> ![Type] -> Type
+ Cryptol.TypeCheck.Type: TPNewtypeParam :: Name -> TPFlavor
+ Cryptol.TypeCheck.Type: TPPrimParam :: Name -> TPFlavor
+ Cryptol.TypeCheck.Type: TPPropSynParam :: Name -> TPFlavor
+ Cryptol.TypeCheck.Type: TPSchemaParam :: Name -> TPFlavor
+ Cryptol.TypeCheck.Type: TPTySynParam :: Name -> TPFlavor
+ Cryptol.TypeCheck.Type: TPUnifyVar :: TPFlavor
+ Cryptol.TypeCheck.Type: instance GHC.Classes.Eq Cryptol.TypeCheck.Type.Newtype
+ Cryptol.TypeCheck.Type: instance GHC.Classes.Ord Cryptol.TypeCheck.Type.Newtype
+ Cryptol.TypeCheck.Type: pIsLiteralLessThan :: Prop -> Maybe (Type, Type)
+ Cryptol.TypeCheck.Type: pLiteralLessThan :: Type -> Type -> Prop
+ Cryptol.TypeCheck.Type: tNewtype :: Newtype -> [Type] -> Type
+ Cryptol.TypeCheck.TypeMap: [tnewtype] :: TypeMap a -> Map Newtype (List TypeMap a)
+ Cryptol.TypeCheck.TypePat: aLiteralLessThan :: Pat Prop (Type, Type)
+ Cryptol.Utils.PP: AutoExponent :: PPFloatExp
+ Cryptol.Utils.PP: FloatFixed :: Int -> PPFloatExp -> PPFloatFormat
+ Cryptol.Utils.PP: FloatFrac :: Int -> PPFloatFormat
+ Cryptol.Utils.PP: FloatFree :: PPFloatExp -> PPFloatFormat
+ Cryptol.Utils.PP: ForceExponent :: PPFloatExp
+ Cryptol.Utils.PP: PPOpts :: Bool -> Int -> Int -> Int -> PPFloatFormat -> PPOpts
+ Cryptol.Utils.PP: [useAscii] :: PPOpts -> Bool
+ Cryptol.Utils.PP: [useBase] :: PPOpts -> Int
+ Cryptol.Utils.PP: [useFPBase] :: PPOpts -> Int
+ Cryptol.Utils.PP: [useFPFormat] :: PPOpts -> PPFloatFormat
+ Cryptol.Utils.PP: [useInfLength] :: PPOpts -> Int
+ Cryptol.Utils.PP: asciiMode :: PPOpts -> Integer -> Bool
+ Cryptol.Utils.PP: data PPFloatExp
+ Cryptol.Utils.PP: data PPFloatFormat
+ Cryptol.Utils.PP: data PPOpts
+ Cryptol.Utils.PP: defaultPPOpts :: PPOpts
+ Cryptol.Utils.PP: instance GHC.Show.Show Cryptol.Utils.PP.PPFloatExp
+ Cryptol.Utils.PP: instance GHC.Show.Show Cryptol.Utils.PP.PPFloatFormat
+ Cryptol.Utils.PP: instance GHC.Show.Show Cryptol.Utils.PP.PPOpts
- Cryptol.Backend: sDelay :: Backend sym => sym -> Maybe String -> SEval sym a -> SEval sym (SEval sym a)
+ Cryptol.Backend: sDelay :: Backend sym => sym -> SEval sym a -> SEval sym (SEval sym a)
- Cryptol.Backend: sDelayFill :: Backend sym => sym -> SEval sym a -> SEval sym a -> SEval sym (SEval sym a)
+ Cryptol.Backend: sDelayFill :: Backend sym => sym -> SEval sym a -> Maybe (SEval sym a) -> String -> SEval sym (SEval sym a)
- Cryptol.Backend.FloatHelpers: BF :: Integer -> Integer -> BigFloat -> BF
+ Cryptol.Backend.FloatHelpers: BF :: !Integer -> !Integer -> !BigFloat -> BF
- Cryptol.Backend.FloatHelpers: [bfExpWidth] :: BF -> Integer
+ Cryptol.Backend.FloatHelpers: [bfExpWidth] :: BF -> !Integer
- Cryptol.Backend.FloatHelpers: [bfPrecWidth] :: BF -> Integer
+ Cryptol.Backend.FloatHelpers: [bfPrecWidth] :: BF -> !Integer
- Cryptol.Backend.FloatHelpers: [bfValue] :: BF -> BigFloat
+ Cryptol.Backend.FloatHelpers: [bfValue] :: BF -> !BigFloat
- Cryptol.Backend.Monad: Eval :: !IO a -> Eval a
+ Cryptol.Backend.Monad: Eval :: !CallStack -> IO a -> Eval a
- Cryptol.Backend.Monad: WordTooWide :: Integer -> EvalError
+ Cryptol.Backend.Monad: WordTooWide :: Integer -> WordTooWide
- Cryptol.Backend.Monad: delayFill :: Eval a -> Eval a -> Eval (Eval a)
+ Cryptol.Backend.Monad: delayFill :: Eval a -> Maybe (Eval a) -> String -> Eval (Eval a)
- Cryptol.Backend.Monad: runEval :: Eval a -> IO a
+ Cryptol.Backend.Monad: runEval :: CallStack -> Eval a -> IO a
- Cryptol.Backend.SBV: SBVError :: !EvalError -> SBVResult a
+ Cryptol.Backend.SBV: SBVError :: !EvalErrorEx -> SBVResult a
- Cryptol.Backend.What4: W4Error :: !EvalError -> W4Result sym a
+ Cryptol.Backend.What4: W4Error :: !EvalErrorEx -> W4Result sym a
- Cryptol.Eval: WordTooWide :: Integer -> EvalError
+ Cryptol.Eval: WordTooWide :: Integer -> WordTooWide
- Cryptol.Eval: evalExpr :: EvalPrims sym => sym -> GenEvalEnv sym -> Expr -> SEval sym (GenValue sym)
+ Cryptol.Eval: evalExpr :: (?range :: Range, EvalPrims sym) => sym -> GenEvalEnv sym -> Expr -> SEval sym (GenValue sym)
- Cryptol.Eval: evalSel :: EvalPrims sym => sym -> GenValue sym -> Selector -> SEval sym (GenValue sym)
+ Cryptol.Eval: evalSel :: Backend sym => sym -> GenValue sym -> Selector -> SEval sym (GenValue sym)
- Cryptol.Eval: evalSetSel :: forall sym. EvalPrims sym => sym -> TValue -> GenValue sym -> Selector -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
+ Cryptol.Eval: evalSetSel :: forall sym. Backend sym => sym -> TValue -> GenValue sym -> Selector -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
- Cryptol.Eval: runEval :: Eval a -> IO a
+ Cryptol.Eval: runEval :: CallStack -> Eval a -> IO a
- Cryptol.Eval.Concrete: primTable :: EvalOpts -> Map PrimIdent Value
+ Cryptol.Eval.Concrete: primTable :: IO EvalOpts -> Map PrimIdent (Prim Concrete)
- Cryptol.Eval.Concrete: toExpr :: PrimMap -> Type -> Value -> Eval (Maybe Expr)
+ Cryptol.Eval.Concrete: toExpr :: PrimMap -> TValue -> Value -> Eval (Maybe Expr)
- Cryptol.Eval.Env: EvalEnv :: !IntMap (SEval sym (GenValue sym)) -> !TypeEnv -> GenEvalEnv sym
+ Cryptol.Eval.Env: EvalEnv :: !IntMap (Either (Prim sym) (SEval sym (GenValue sym))) -> !TypeEnv -> GenEvalEnv sym
- Cryptol.Eval.Env: [envVars] :: GenEvalEnv sym -> !IntMap (SEval sym (GenValue sym))
+ Cryptol.Eval.Env: [envVars] :: GenEvalEnv sym -> !IntMap (Either (Prim sym) (SEval sym (GenValue sym)))
- Cryptol.Eval.Env: bindVarDirect :: Backend sym => Name -> GenValue sym -> GenEvalEnv sym -> GenEvalEnv sym
+ Cryptol.Eval.Env: bindVarDirect :: Backend sym => Name -> Prim sym -> GenEvalEnv sym -> GenEvalEnv sym
- Cryptol.Eval.Env: lookupVar :: Name -> GenEvalEnv sym -> Maybe (SEval sym (GenValue sym))
+ Cryptol.Eval.Env: lookupVar :: Name -> GenEvalEnv sym -> Maybe (Either (Prim sym) (SEval sym (GenValue sym)))
- Cryptol.Eval.Generic: binary :: Backend sym => Binary sym -> GenValue sym
+ Cryptol.Eval.Generic: binary :: Backend sym => Binary sym -> Prim sym
- Cryptol.Eval.Generic: ecFractionV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: ecFractionV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: ecNumberV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: ecNumberV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: ecSplitV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: ecSplitV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: expV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: expV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: fieldDivideV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: fieldDivideV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: foldl'V :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: foldl'V :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: foldlV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: foldlV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: fpBinArithV :: Backend sym => sym -> FPArith2 sym -> GenValue sym
+ Cryptol.Eval.Generic: fpBinArithV :: Backend sym => sym -> FPArith2 sym -> Prim sym
- Cryptol.Eval.Generic: fromIntegerV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: fromIntegerV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: fromThenToV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: fromThenToV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: fromToV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: fromToV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: fromZV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: fromZV :: Backend sym => sym -> Prim 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)) -> 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: infFromThenV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: infFromThenV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: infFromV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: infFromV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: lg2V :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: lg2V :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: logicShift :: Backend sym => sym -> String -> (sym -> Nat' -> TValue -> SInteger sym -> SEval sym (SInteger sym)) -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> (Nat' -> Integer -> Integer -> Maybe Integer) -> (Nat' -> Integer -> Integer -> Maybe Integer) -> GenValue sym
+ Cryptol.Eval.Generic: logicShift :: Backend sym => sym -> String -> (sym -> Nat' -> TValue -> SInteger sym -> SEval sym (SInteger sym)) -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> (SWord sym -> SWord sym -> SEval sym (SWord sym)) -> (Nat' -> Integer -> Integer -> Maybe Integer) -> (Nat' -> Integer -> Integer -> Maybe Integer) -> Prim sym
- Cryptol.Eval.Generic: parmapV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: parmapV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: ratioV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: ratioV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: recipV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: recipV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: sdivV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: sdivV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: smodV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: smodV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: toIntegerV :: Backend sym => sym -> GenValue sym
+ Cryptol.Eval.Generic: toIntegerV :: Backend sym => sym -> Prim sym
- Cryptol.Eval.Generic: unary :: Backend sym => Unary sym -> GenValue sym
+ Cryptol.Eval.Generic: unary :: Backend sym => Unary 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 -> Either (SInteger sym) (WordValue sym) -> SEval sym (GenValue sym) -> 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: wordValUnaryOp :: Backend sym => (SBit sym -> SEval sym (SBit sym)) -> (SWord sym -> SEval sym (SWord 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.SBV: primTable :: SBV -> Map PrimIdent Value
+ Cryptol.Eval.SBV: primTable :: SBV -> IO EvalOpts -> Map PrimIdent (Prim SBV)
- Cryptol.Eval.Value: VFun :: (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -> GenValue sym
+ Cryptol.Eval.Value: VFun :: CallStack -> (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -> GenValue sym
- Cryptol.Eval.Value: VNumPoly :: (Nat' -> SEval sym (GenValue sym)) -> GenValue sym
+ Cryptol.Eval.Value: VNumPoly :: CallStack -> (Nat' -> SEval sym (GenValue sym)) -> GenValue sym
- Cryptol.Eval.Value: VPoly :: (TValue -> SEval sym (GenValue sym)) -> GenValue sym
+ Cryptol.Eval.Value: VPoly :: CallStack -> (TValue -> SEval sym (GenValue sym)) -> GenValue sym
- Cryptol.Eval.Value: finiteSeqMap :: Backend sym => sym -> [SEval sym (GenValue sym)] -> SeqMap sym
+ Cryptol.Eval.Value: finiteSeqMap :: [SEval sym (GenValue sym)] -> SeqMap sym
- Cryptol.Eval.Value: flam :: Backend sym => (SFloat sym -> SEval sym (GenValue sym)) -> GenValue sym
+ Cryptol.Eval.Value: flam :: Backend sym => sym -> (SFloat sym -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: fromVFun :: GenValue sym -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
+ Cryptol.Eval.Value: fromVFun :: Backend sym => sym -> GenValue sym -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: fromVNumPoly :: GenValue sym -> Nat' -> SEval sym (GenValue sym)
+ Cryptol.Eval.Value: fromVNumPoly :: Backend sym => sym -> GenValue sym -> Nat' -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: fromVPoly :: GenValue sym -> TValue -> SEval sym (GenValue sym)
+ Cryptol.Eval.Value: fromVPoly :: Backend sym => sym -> GenValue sym -> TValue -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: ilam :: Backend sym => (Integer -> GenValue sym) -> GenValue sym
+ Cryptol.Eval.Value: ilam :: Backend sym => sym -> (Integer -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: infiniteSeqMap :: Backend sym => [SEval sym (GenValue sym)] -> SEval sym (SeqMap sym)
+ Cryptol.Eval.Value: infiniteSeqMap :: Backend sym => sym -> [SEval sym (GenValue sym)] -> SEval sym (SeqMap sym)
- Cryptol.Eval.Value: lam :: (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -> GenValue sym
+ Cryptol.Eval.Value: lam :: Backend sym => sym -> (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: mapSeqMap :: Backend sym => (GenValue sym -> SEval sym (GenValue sym)) -> SeqMap sym -> SEval sym (SeqMap sym)
+ Cryptol.Eval.Value: mapSeqMap :: Backend sym => sym -> (GenValue sym -> SEval sym (GenValue sym)) -> SeqMap sym -> SEval sym (SeqMap sym)
- Cryptol.Eval.Value: memoMap :: (MonadIO m, Backend sym) => SeqMap sym -> m (SeqMap sym)
+ Cryptol.Eval.Value: memoMap :: Backend sym => sym -> SeqMap sym -> SEval sym (SeqMap sym)
- Cryptol.Eval.Value: nlam :: Backend sym => (Nat' -> GenValue sym) -> GenValue sym
+ Cryptol.Eval.Value: nlam :: Backend sym => sym -> (Nat' -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: sDelayFill :: Backend sym => sym -> SEval sym a -> SEval sym a -> SEval sym (SEval sym a)
+ Cryptol.Eval.Value: sDelayFill :: Backend sym => sym -> SEval sym a -> Maybe (SEval sym a) -> String -> SEval sym (SEval sym a)
- Cryptol.Eval.Value: tlam :: Backend sym => (TValue -> GenValue sym) -> GenValue sym
+ Cryptol.Eval.Value: tlam :: Backend sym => sym -> (TValue -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: toStream :: Backend sym => [GenValue sym] -> SEval sym (GenValue sym)
+ Cryptol.Eval.Value: toStream :: Backend sym => sym -> [GenValue sym] -> SEval sym (GenValue sym)
- Cryptol.Eval.Value: zipSeqMap :: Backend sym => (GenValue sym -> GenValue sym -> SEval sym (GenValue sym)) -> SeqMap sym -> SeqMap sym -> SEval sym (SeqMap sym)
+ Cryptol.Eval.Value: zipSeqMap :: Backend sym => sym -> (GenValue sym -> GenValue sym -> SEval sym (GenValue sym)) -> SeqMap sym -> SeqMap sym -> SEval sym (SeqMap sym)
- Cryptol.Eval.What4: primTable :: IsSymExprBuilder sym => What4 sym -> Map PrimIdent (Value sym)
+ Cryptol.Eval.What4: primTable :: IsSymExprBuilder sym => What4 sym -> IO EvalOpts -> Map PrimIdent (Prim (What4 sym))
- Cryptol.ModuleSystem: type ModuleCmd a = (EvalOpts, FilePath -> IO ByteString, ModuleEnv) -> IO (ModuleRes a)
+ Cryptol.ModuleSystem: type ModuleCmd a = ModuleInput IO -> IO (ModuleRes a)
- Cryptol.ModuleSystem.Base: TCLinter :: (o -> InferInput -> Either Error [ProofObligation]) -> Maybe ModName -> TCLinter o
+ Cryptol.ModuleSystem.Base: TCLinter :: (o -> InferInput -> Either (Range, Error) [ProofObligation]) -> Maybe ModName -> TCLinter o
- Cryptol.ModuleSystem.Base: [lintCheck] :: TCLinter o -> o -> InferInput -> Either Error [ProofObligation]
+ Cryptol.ModuleSystem.Base: [lintCheck] :: TCLinter o -> o -> InferInput -> Either (Range, Error) [ProofObligation]
- Cryptol.ModuleSystem.Monad: RO :: [ImportSource] -> EvalOpts -> (FilePath -> m ByteString) -> RO m
+ Cryptol.ModuleSystem.Monad: RO :: [ImportSource] -> m EvalOpts -> Bool -> (FilePath -> m ByteString) -> Solver -> RO m
- Cryptol.ModuleSystem.Monad: [roEvalOpts] :: RO m -> EvalOpts
+ Cryptol.ModuleSystem.Monad: [roEvalOpts] :: RO m -> m EvalOpts
- Cryptol.ModuleSystem.Monad: emptyRO :: EvalOpts -> (FilePath -> m ByteString) -> RO m
+ Cryptol.ModuleSystem.Monad: emptyRO :: ModuleInput m -> RO m
- Cryptol.ModuleSystem.Monad: runModuleM :: (EvalOpts, FilePath -> IO ByteString, ModuleEnv) -> ModuleM a -> IO (Either ModuleError (a, ModuleEnv), [ModuleWarning])
+ Cryptol.ModuleSystem.Monad: runModuleM :: ModuleInput IO -> ModuleM a -> IO (Either ModuleError (a, ModuleEnv), [ModuleWarning])
- Cryptol.ModuleSystem.Monad: runModuleT :: Monad m => (EvalOpts, FilePath -> m ByteString, ModuleEnv) -> ModuleT m a -> m (Either ModuleError (a, ModuleEnv), [ModuleWarning])
+ Cryptol.ModuleSystem.Monad: runModuleT :: Monad m => ModuleInput m -> ModuleT m a -> m (Either ModuleError (a, ModuleEnv), [ModuleWarning])
- Cryptol.Parser: Config :: !FilePath -> !Layout -> PreProc -> [FilePath] -> Bool -> Config
+ Cryptol.Parser: Config :: !FilePath -> !Position -> !Layout -> PreProc -> [FilePath] -> Bool -> Config
- Cryptol.Parser: HappyErrorMsg :: Range -> String -> ParseError
+ Cryptol.Parser: HappyErrorMsg :: Range -> [String] -> ParseError
- Cryptol.Parser.AST: EFun :: [Pattern n] -> Expr n -> Expr n
+ Cryptol.Parser.AST: EFun :: FunDesc n -> [Pattern n] -> Expr n -> Expr n
- Cryptol.Parser.AST: Newtype :: Located name -> [TParam name] -> [Named (Type name)] -> Newtype name
+ Cryptol.Parser.AST: Newtype :: Located name -> [TParam name] -> Rec (Type name) -> Newtype name
- Cryptol.Parser.AST: [nBody] :: Newtype name -> [Named (Type name)]
+ Cryptol.Parser.AST: [nBody] :: Newtype name -> Rec (Type name)
- Cryptol.Parser.Lexer: Config :: !FilePath -> !Layout -> PreProc -> [FilePath] -> Bool -> Config
+ Cryptol.Parser.Lexer: Config :: !FilePath -> !Position -> !Layout -> PreProc -> [FilePath] -> Bool -> Config
- Cryptol.REPL.Command: Command :: REPL () -> Command
+ Cryptol.REPL.Command: Command :: (Int -> Maybe FilePath -> REPL ()) -> Command
- Cryptol.REPL.Command: ExprArg :: (String -> REPL ()) -> CommandBody
+ Cryptol.REPL.Command: ExprArg :: (String -> (Int, Int) -> Maybe FilePath -> REPL ()) -> CommandBody
- Cryptol.REPL.Command: FileExprArg :: (FilePath -> String -> REPL ()) -> CommandBody
+ Cryptol.REPL.Command: FileExprArg :: (FilePath -> String -> (Int, Int) -> Maybe FilePath -> REPL ()) -> CommandBody
- Cryptol.REPL.Command: offlineProveSat :: String -> QueryType -> String -> Maybe FilePath -> REPL ()
+ Cryptol.REPL.Command: offlineProveSat :: String -> QueryType -> Expr -> Schema -> Maybe FilePath -> REPL ()
- Cryptol.REPL.Command: onlineProveSat :: String -> QueryType -> String -> Maybe FilePath -> REPL (Maybe String, ProverResult, ProverStats)
+ Cryptol.REPL.Command: onlineProveSat :: String -> QueryType -> Expr -> Schema -> Maybe FilePath -> REPL (Maybe String, ProverResult, ProverStats)
- Cryptol.REPL.Command: proveCmd :: String -> REPL ()
+ Cryptol.REPL.Command: proveCmd :: String -> (Int, Int) -> Maybe FilePath -> REPL ()
- Cryptol.REPL.Command: qcCmd :: QCMode -> String -> REPL [TestReport]
+ Cryptol.REPL.Command: qcCmd :: QCMode -> String -> (Int, Int) -> Maybe FilePath -> REPL ()
- Cryptol.REPL.Command: replParseExpr :: String -> REPL (Expr PName)
+ Cryptol.REPL.Command: replParseExpr :: String -> (Int, Int) -> Maybe FilePath -> REPL (Expr PName)
- Cryptol.REPL.Command: runCommand :: Command -> REPL CommandExitCode
+ Cryptol.REPL.Command: runCommand :: Int -> Maybe FilePath -> Command -> REPL CommandExitCode
- Cryptol.REPL.Command: satCmd :: String -> REPL ()
+ Cryptol.REPL.Command: satCmd :: String -> (Int, Int) -> Maybe FilePath -> REPL ()
- Cryptol.REPL.Command: splitCommand :: String -> Maybe (String, String)
+ Cryptol.REPL.Command: splitCommand :: String -> Maybe (Int, String, String)
- Cryptol.REPL.Monad: EvalError :: EvalError -> REPLException
+ Cryptol.REPL.Monad: EvalError :: EvalErrorEx -> REPLException
- Cryptol.REPL.Monad: OptionDescr :: String -> EnvVal -> Checker -> String -> (EnvVal -> REPL ()) -> OptionDescr
+ Cryptol.REPL.Monad: OptionDescr :: String -> [String] -> EnvVal -> Checker -> String -> (EnvVal -> REPL ()) -> OptionDescr
- Cryptol.REPL.Monad: getPropertyNames :: REPL ([Name], NameDisp)
+ Cryptol.REPL.Monad: getPropertyNames :: REPL ([(Name, IfaceDecl)], NameDisp)
- Cryptol.REPL.Monad: runREPL :: Bool -> Logger -> REPL a -> IO a
+ Cryptol.REPL.Monad: runREPL :: Bool -> Bool -> Logger -> REPL a -> IO a
- Cryptol.Symbolic: FTSeq :: Int -> FinType -> FinType
+ Cryptol.Symbolic: FTSeq :: Integer -> FinType -> FinType
- Cryptol.Symbolic: ThmResult :: [Type] -> ProverResult
+ Cryptol.Symbolic: ThmResult :: [TValue] -> ProverResult
- Cryptol.Symbolic: computeModel :: PrimMap -> [FinType] -> [VarShape Concrete] -> [(Type, Expr, Value)]
+ Cryptol.Symbolic: computeModel :: PrimMap -> [FinType] -> [VarShape Concrete] -> [(TValue, Expr, Value)]
- Cryptol.Symbolic: unFinType :: FinType -> Type
+ Cryptol.Symbolic: unFinType :: FinType -> TValue
- Cryptol.Testing.Random: FailError :: EvalError -> [Value] -> TestResult
+ Cryptol.Testing.Random: FailError :: EvalErrorEx -> [Value] -> TestResult
- 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 -> SolverConfig -> [FilePath] -> !PrimMap -> !Supply -> 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 -> SolverConfig -> [FilePath] -> !PrimMap -> !Supply -> Solver -> InferInput
- Cryptol.TypeCheck.Depends: orderTyDecls :: [TyDecl] -> InferM [TyDecl]
+ Cryptol.TypeCheck.Depends: orderTyDecls :: [TyDecl] -> InferM (Either Error [TyDecl])
- Cryptol.TypeCheck.InferTypes: Goals :: Set Goal -> Set Prop -> Map TVar LitGoal -> Goals
+ Cryptol.TypeCheck.InferTypes: Goals :: Set Goal -> Set Prop -> Map TVar LitGoal -> Map TVar LitGoal -> Goals
- 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 -> SolverConfig -> [FilePath] -> !PrimMap -> !Supply -> 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 -> SolverConfig -> [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 -> Solver -> !PrimMap -> !IORef Int -> RO
+ 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.Sanity: tcDecls :: InferInput -> [DeclGroup] -> Either Error [ProofObligation]
+ Cryptol.TypeCheck.Sanity: tcDecls :: InferInput -> [DeclGroup] -> Either (Range, Error) [ProofObligation]
- Cryptol.TypeCheck.Sanity: tcExpr :: InferInput -> Expr -> Either Error (Schema, [ProofObligation])
+ Cryptol.TypeCheck.Sanity: tcExpr :: InferInput -> Expr -> Either (Range, Error) (Schema, [ProofObligation])
- Cryptol.TypeCheck.Sanity: tcModule :: InferInput -> Module -> Either Error [ProofObligation]
+ Cryptol.TypeCheck.Sanity: tcModule :: InferInput -> Module -> Either (Range, Error) [ProofObligation]
- Cryptol.TypeCheck.Type: Newtype :: Name -> [TParam] -> [Prop] -> [(Ident, Type)] -> Maybe Text -> Newtype
+ Cryptol.TypeCheck.Type: Newtype :: Name -> [TParam] -> [Prop] -> RecordMap Ident Type -> Maybe Text -> Newtype
- Cryptol.TypeCheck.Type: [ntFields] :: Newtype -> [(Ident, Type)]
+ Cryptol.TypeCheck.Type: [ntFields] :: Newtype -> RecordMap Ident Type
- Cryptol.TypeCheck.TypeMap: TM :: Map TVar a -> Map TCon (List TypeMap a) -> Map [Ident] (List TypeMap a) -> TypeMap a
+ Cryptol.TypeCheck.TypeMap: TM :: Map TVar a -> Map TCon (List TypeMap a) -> Map [Ident] (List TypeMap a) -> Map Newtype (List TypeMap a) -> TypeMap a

Files

CHANGES.md view
@@ -1,3 +1,53 @@+# 2.11.0++## Language changes++* The `newtype` construct, which has existed in the interpreter in an+  incomplete and undocumented form for quite a while, is now fullly+  supported. The construct is documented in section 1.22 of [Programming+  Cryptol](https://cryptol.net/files/ProgrammingCryptol.pdf). Note,+  however, that the `cryptol-remote-api` RPC server currently does not+  include full support for referring to `newtype` names, though it can+  work with implementations that use `newtype` internally.++## New features++* By default, the interpreter will now track source locations of+  expressions being evaluated, and retain call stack information.+  This information is incorporated into error messages arising from+  runtime errors. This additional bookkeeping incurs significant+  runtime overhead, but may be disabled using the `--no-call-stacks`+  command-line option.++* The `:exhaust` command now works for floating-point types and the+  `:check` command now uses more representative sampling of+  floating-point input values to test.++* The `cryptol-remote-api` RPC server now has methods corresponding to+  the `:prove` and `:sat` commands in the REPL.++* The `cryptol-eval-server` executable is a new, stateless server+  providing a subset of the functionality of `cryptol-remote-api`+  dedicated entirely to invoking Cryptol functions on concrete inputs.++## Internal changes++* A single running instance of the SMT solver used for type checking+  (Z3) is now used to check a larger number of type correctness queries.+  This means that fewer solver instances are invoked, and type checking+  should generally be faster.++* The Cryptol interpreter now builds against `libBF` version 0.6, which+  fixes a few bugs in the evaluation of floating-point operations.++## Bug fixes++* Closed issues #118, #398, #426, #470, #491, #567, #594, #639, #656,+  #698, #743, #810, #858, #870, #905, #915, #917, #962, #973, #975,+  #980, #984, #986, #990, #996, #997, #1002, #1006, #1009, #1012, #1024,+  #1030, #1035, #1036, #1039, #1040, #1044, #1045, #1049, #1050, #1051,+  #1052, #1063, #1092, #1093, #1094, and #1100.+ # 2.10.0  ## Language changes
cryptol.cabal view
@@ -1,6 +1,6 @@ Cabal-version:       2.4 Name:                cryptol-Version:             2.10.0+Version:             2.11.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,7 @@ source-repository this   type:     git   location: https://github.com/GaloisInc/cryptol.git-  tag:      2.10.0+  tag:      2.11.0   flag static@@ -56,7 +56,7 @@                        GraphSCC          >= 1.0.4,                        heredoc           >= 0.2,                        integer-gmp       >= 1.0 && < 1.1,-                       libBF             >= 0.5.1,+                       libBF             >= 0.6 && < 0.7,                        MemoTrie          >= 0.6 && < 0.7,                        monad-control     >= 1.0,                        monadLib          >= 3.7.2,@@ -64,7 +64,7 @@                        pretty            >= 1.1,                        process           >= 1.2,                        random            >= 1.0.1,-                       sbv               >= 8.6 && < 8.8,+                       sbv               >= 8.6 && < 8.13,                        simple-smt        >= 0.7.1,                        stm               >= 2.4,                        strict,@@ -74,7 +74,7 @@                        mtl               >= 2.2.1,                        time              >= 1.6.0.1,                        panic             >= 0.3,-                       what4             >= 1.0 && < 1.1+                       what4             >= 1.1 && < 1.2    Build-tool-depends:  alex:alex, happy:happy   hs-source-dirs:      src@@ -164,12 +164,12 @@                        Cryptol.Backend.Monad,                        Cryptol.Backend.SBV,                        Cryptol.Backend.What4,-                       Cryptol.Backend.What4.SFloat,                         Cryptol.Eval,                        Cryptol.Eval.Concrete,                        Cryptol.Eval.Env,                        Cryptol.Eval.Generic,+                       Cryptol.Eval.Prims,                        Cryptol.Eval.Reference,                        Cryptol.Eval.SBV,                        Cryptol.Eval.Type,@@ -232,7 +232,8 @@      ghc-options: -Wno-redundant-constraints    if os(linux) && flag(static)-      ld-options:      -static -pthread+      ld-options: -static -pthread+      ghc-options: -optl-fuse-ld=bfd  executable cryptol-html   Default-language:@@ -242,6 +243,27 @@   build-depends: base, text, cryptol, blaze-html   GHC-options: -Wall +  if os(linux) && flag(static)+      ld-options: -static -pthread+      ghc-options: -optl-fuse-ld=bfd++executable check-exercises+  Default-language:+    Haskell2010+  Main-is:             CheckExercises.hs+  hs-source-dirs:      cryptol+  build-depends:       ansi-terminal+                     , base+                     , containers+                     , directory+                     , extra+                     , filepath+                     , mtl+                     , optparse-applicative+                     , process+                     , temporary+                     , text+  GHC-options: -Wall benchmark cryptol-bench   type:                exitcode-stdio-1.0   main-is:             Main.hs@@ -251,7 +273,8 @@   if impl(ghc >= 8.0.1)      ghc-options: -Wno-redundant-constraints   if os(linux) && flag(static)-      ld-options:      -static -pthread+      ld-options: -static -pthread+      ghc-options: -optl-fuse-ld=bfd   build-depends:       base                      , criterion                      , cryptol
+ cryptol/CheckExercises.hs view
@@ -0,0 +1,371 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ViewPatterns #-}++module Main(main) where++import Control.Monad.State+import Options.Applicative+import Data.Char (isSpace, isAlpha)+import Data.Foldable (traverse_)+import Data.List (isInfixOf, isPrefixOf, stripPrefix)+import Data.Maybe (fromMaybe)+import qualified Data.Sequence as Seq+import Numeric.Natural+import qualified System.Process as P+import System.Directory+import System.Exit+import System.IO.Temp+import Data.Foldable (toList)++data Opts = Opts { latexFile :: FilePath+                   -- ^ The latex file we are going to check+                 , cryptolExe :: Maybe FilePath+                   -- ^ Path to cryptol executable (default: cabal v2-exec cryptol)+                 , tempDir :: Maybe FilePath+                   -- ^ Path to store temporary files and log files+                 }+  deriving Show++optsParser :: Parser Opts+optsParser = Opts+  <$> strArgument (  help "path to latex file"+                  <> metavar "PATH"+                  )+  <*> ( optional $ strOption+        (  long "exe"+        <> short 'e'+        <> metavar "PATH"+        <> help "Path to cryptol executable (defaults to 'cabal v2-exec cryptol')"+        ) )+  <*> ( optional $ strOption+        (  long "log-dir"+        <> short 'l'+        <> metavar "PATH"+        <> help "Directory for log files in case of failure (defaults to .)"+        ) )++-- | Trim whitespace off both ends of a string+trim :: String -> String+trim = f . f+   where f = reverse . dropWhile isSpace++----------------------------------------------------------------------+-- LaTeX processing state monad+--+-- We process the text-by-line. The behavior of the state monad on a line is+-- governed by the mode it is currently in. The current mode dictates how to+-- interpret each line, and which mode to transition to next.+--+-- There are four modes: AwaitingReplMode, ReplinMode, ReploutMode, and+-- ReplPromptMode. Below we describe the behavior of each mode.+--+-- AwaitingReplMode: When in this mode, we are anticipating "replin" or+-- "replout" lines; that is, lines that will be issued as input to the repl or+-- expected as output from the repl.. When we see a \begin{replinVerb}, we+-- transition to ReplinMode. When we see a \begin{reploutVerb}, we transition to+-- ReploutMode. When we see a \begin{replPromptVerb}, we transition to+-- ReplPromptMode. When we see an inline \replin{..} command, we add the content+-- to the list of replin lines without changing modes. When we see an inline+-- \replout{..} command, we add the content to the list of replout lines without+-- changing modes.+--+-- ReplinMode: When in this mode, we are inside of a "\begin{replinVerb}"+-- section. When we see a \end{replinVerb} line, we transition to+-- AwaitingReplMode. Otherwise, we simply add the entire line to the list of+-- replin lines.+--+-- ReploutMode: Like ReplinMode, except we add each line to the expected output.+--+-- ReplPromptMode: A combination of ReplinMode and ReploutMode. Each line is+-- either added to input or expected output. If the line starts with a prompt+-- like "Cryptol>" or "Float>", it is added to expected input. Otherwise it is+-- added to expected output.++data PMode = AwaitingReplMode+           | ReplinMode+           | ReploutMode+           | ReplPromptMode+  deriving (Eq, Show)++data Line = Line { lineNum :: Natural+                 , lineText :: String+                 }+  deriving (Eq, Show)++-- | REPL input and expected output, with line number annotations.+data ReplData = ReplData { rdReplin  :: Seq.Seq Line+                         , rdReplout :: Seq.Seq Line+                         }+  deriving (Eq, Show)++-- | Latex processing state+data PState = PState { pMode              :: PMode+                       -- ^ current mode+                     , pCompletedReplData :: Seq.Seq ReplData+                       -- ^ list of all completed REPL input/output pairs to be+                       -- validated (thus far)+                     , pReplin            :: Seq.Seq Line+                       -- ^ list of replin lines (so far) for unfinished ReplData+                     , pReplout           :: Seq.Seq Line+                       -- ^ list of replout lines (so far) for unfinished ReplData+                     , pCurrentLine       :: Natural+                     }+  deriving (Eq, Show)++initPState :: PState+initPState = PState AwaitingReplMode Seq.empty Seq.empty Seq.empty 1++-- | P monad for reading in lines+type P = State PState++first3  :: (a -> a') -> (a, b, c) -> (a', b, c)+first3 f (a, b, c) = (f a, b, c)++-- | Like 'stripPrefix', but takes a list of prefixes rather than a single+-- prefix. Returns the first prefix that matches the start of the list along+-- with the remainder of the list.+stripPrefixOneOf :: Eq a => [[a]] -> [a] -> Maybe ([a], [a])+stripPrefixOneOf [] _ = Nothing+stripPrefixOneOf (p:ps) as = case stripPrefix p as of+  Nothing -> stripPrefixOneOf ps as+  Just as' -> Just (p, as')++-- | Like 'stripInfix', but takes a list of infixes. Returns the infix that+-- matches at the earliest index.+stripInfixOneOf :: Eq a => [[a]] -> [a] -> Maybe ([a], [a], [a])+stripInfixOneOf needles haystack+  | Just (needle, suffix) <- stripPrefixOneOf needles haystack+  = Just ([], needle, suffix)+stripInfixOneOf _ [] = Nothing+stripInfixOneOf needles (x:xs) = first3 (x:) <$> stripInfixOneOf needles xs++data InlineRepl = InlineReplin | InlineReplout++-- | Extracts the first inline repl command returns the type of command, its+-- contents, and the remainder of the string.+inlineRepl :: String -> Maybe (InlineRepl, String, String)+inlineRepl s+  | Just (_, ir, s1) <- stripInfixOneOf [ "\\replin|"+                                        , "\\replout|"+                                        , "\\hidereplin|"+                                        , "\\hidereplout|"] s+  , (s2, s3) <- break (=='|') s1 = case ir of+      "\\replin|" -> Just (InlineReplin, s2, s3)+      "\\replout|" -> Just (InlineReplout, s2, s3)+      "\\hidereplin|" -> Just (InlineReplin, s2, s3)+      "\\hidereplout|" -> Just (InlineReplout, s2, s3)+      _ -> error "PANIC: CheckExercises.inlineRepl"+  | otherwise = Nothing++addReplData :: P ()+addReplData = do+  replin <- gets pReplin+  replout <- gets pReplout+  completedReplData <- gets pCompletedReplData+  let completedReplData' = completedReplData Seq.|> ReplData replin replout+  when (not (Seq.null replin && Seq.null replout)) $+    modify' $ \st -> st { pCompletedReplData = completedReplData'+                        , pReplin = Seq.empty+                        , pReplout = Seq.empty+                        }++addReplin :: String -> P ()+addReplin s = do+  ln <- gets pCurrentLine+  replin <- gets pReplin+  modify' $ \st -> st { pReplin = replin Seq.|> Line ln s }++addReplout :: String -> P ()+addReplout s = do+  ln <- gets pCurrentLine+  replout <- gets pReplout+  modify' $ \st -> st { pReplout = replout Seq.|> Line ln s }++nextLine :: P ()+nextLine = modify' $ \st -> st { pCurrentLine = pCurrentLine st + 1 }++stripPrompt :: String -> Maybe String+stripPrompt s = case span isAlpha s of+  (_:_, '>':s') -> Just s'+  _ -> Nothing++-- | The main function for our monad. Input is a single line.+processLine :: String -> P ()+processLine s = do+  let s_nocomment = takeWhile (not . (== '%')) s+      s_nowhitespace = filter (not . isSpace) s_nocomment+  m <- gets pMode+  ln <- gets pCurrentLine+  case m of+    AwaitingReplMode+      | "\\begin{replinVerb}" `isInfixOf` s_nowhitespace -> do+          modify' $ \st -> st { pMode = ReplinMode }+          nextLine+      | "\\begin{reploutVerb}" `isInfixOf` s_nowhitespace -> do+          modify' $ \st -> st { pMode = ReploutMode }+          nextLine+      | "\\begin{replPrompt}" `isInfixOf` s_nowhitespace -> do+          modify' $ \st -> st { pMode = ReplPromptMode }+          nextLine+      | "\\restartrepl" `isInfixOf` s_nowhitespace -> do+          -- This is a command that acts as the barrier between discrete+          -- input/output pairs. When we see it, we commit the current pair,+          -- begin a brand new pair, and advance to the next line.+          addReplData+          nextLine+      | Just (InlineReplin, cmd, rst) <- inlineRepl s -> do+          addReplin cmd+          processLine rst+      | Just (InlineReplout, cmd, rst) <- inlineRepl s -> do+          addReplout cmd+          processLine rst+      | otherwise -> nextLine+    ReplinMode+      | "\\end{replinVerb}" `isInfixOf` s_nowhitespace -> do+          -- Switching from ingesting repl input to awaiting repl input.+          modify' $ \st -> st { pMode = AwaitingReplMode }+          nextLine+      | otherwise -> do+          -- Ingest the current line, and stay in ReplinMode.+          replin <- gets pReplin+          let replin' = replin Seq.|> Line ln s -- use the full input since %+                                                -- isn't a comment in verbatim+                                                -- mode.+          modify' $ \st -> st { pReplin = replin' }+          nextLine+    ReploutMode+      | "\\end{reploutVerb}" `isInfixOf` s_nowhitespace -> do+          -- Switching from ingesting repl output to awaiting repl output.+          modify' $ \st -> st { pMode = AwaitingReplMode }+          nextLine+      | otherwise -> do+          -- Ingest the current line, and stay in ReploutMode.+          replout <- gets pReplout+          let replout' = replout Seq.|> Line ln s -- use the full input since %+                                                  -- isn't a comment in verbatim+                                                  -- mode.+          modify' $ \st -> st { pReplout = replout' }+          nextLine+    ReplPromptMode+      | "\\end{replPrompt}" `isInfixOf` s_nowhitespace -> do+          -- Switching from ingesting repl input/output to awaiting repl+          -- input.+          modify' $ \st -> st { pMode = AwaitingReplMode }+          nextLine+      | Just input <- stripPrompt (trim s) -> do+          replin <- gets pReplin+          let input' = trim input+              replin' = replin Seq.|> Line ln input' -- use the full input since+                                                     -- % isn't a comment in+                                                     -- verbatim mode.+          modify $ \st -> st { pReplin = replin' }+          nextLine+      | otherwise -> do+          replout <- gets pReplout+          let replout' = replout Seq.|> Line ln s -- use the full input since %+                                                  -- isn't a comment in verbatim+                                                  -- mode.+          modify $ \st -> st { pReplout = replout' }+          nextLine++main :: IO ()+main = do+  opts <- execParser p+  allLines <- lines <$> readFile (latexFile opts)+  let PState {..} = flip execState initPState $ do+        -- Process every line+        traverse_ processLine allLines+        -- Insert the final ReplData upon completion+        addReplData+  let allReplData = toList pCompletedReplData+      dir = fromMaybe "." (tempDir opts)++  forM_ allReplData $ \rd -> do+    let inText = unlines $ fmap (trim . lineText) $ toList $ rdReplin rd+        inFileNameTemplate = "in.icry"+    inFile <- writeTempFile dir inFileNameTemplate inText++    let exe = fromMaybe "./cry run" (cryptolExe opts)++    if Seq.null (rdReplout rd)+      then do let cryCmd = (P.shell (exe ++ " --interactive-batch " ++ inFile ++ " -e"))+              (cryEC, cryOut, _) <- P.readCreateProcessWithExitCode cryCmd ""+++              Line lnReplinStart _ Seq.:<| _ <- return $ rdReplin rd+              _ Seq.:|> Line lnReplinEnd _ <- return $ rdReplin rd+              case cryEC of+                ExitFailure _ -> do+                  putStrLn $ "REPL error (replin lines " +++                    show lnReplinStart ++ "-" ++ show lnReplinEnd ++ ")."+                  putStr cryOut+                  exitFailure+                ExitSuccess -> do+                  -- remove temporary input file+                  removeFile inFile+      else do let outExpectedText = unlines $ filter (not . null) $+                    fmap (trim . lineText) $ toList $ rdReplout rd+                  outExpectedFileNameTemplate = "out-expected.icry"+                  outFileNameTemplate = "out.icry"+                  cryCmd = (P.shell (exe ++ " --interactive-batch " ++ inFile))+              outExpectedFile <- writeTempFile dir outExpectedFileNameTemplate outExpectedText+              outFile <- emptyTempFile dir outFileNameTemplate++              (_, cryOut, _) <- P.readCreateProcessWithExitCode cryCmd ""++              -- remove temporary input file+              removeFile inFile++              let outText = unlines $ filter (not . null) $ trim <$> (dropWhile ("Loading module" `isPrefixOf`) $ lines cryOut)++              writeFile outFile outText++              let diffCmd = (P.shell ("diff -u " ++ outExpectedFile ++ " " ++ outFile))++              (diffEC, diffOut, _) <- P.readCreateProcessWithExitCode diffCmd ""+              case diffEC of+                ExitSuccess -> do+                  -- Remove temporary output files+                  removeFile outExpectedFile+                  removeFile outFile+                ExitFailure _ -> do+                  Line lnReplinStart _ Seq.:<| _ <- return $ rdReplin rd+                  _ Seq.:|> Line lnReplinEnd _ <- return $ rdReplin rd+                  Line lnReploutStart _ Seq.:<| _ <- return $ rdReplout rd+                  _ Seq.:|> Line lnReploutEnd _ <- return $ rdReplout rd++                  putStrLn $ "REPL output mismatch in " ++ latexFile opts+                  putStrLn $ "  (replin lines " +++                    show lnReplinStart ++ "-" ++ show lnReplinEnd +++                    ", replout lines " ++ show lnReploutStart ++ "-" +++                    show lnReploutEnd ++ ")."+                  putStrLn $ "Diff output:"+                  putStr diffOut++                  let outExpectedFileName = dir ++ "/" ++ outExpectedFileNameTemplate+                      outFileName = dir ++ "/" ++ outFileNameTemplate++                  putStrLn ""+                  putStrLn $ "Expected output written to: " ++ outExpectedFileName+                  putStrLn $ "Actual output written to: " ++ outFileName++                  -- Write to log files+                  writeFile outExpectedFileName outExpectedText+                  writeFile outFileName outText++                  -- Remove temporary output files and exit+                  removeFile outExpectedFile+                  removeFile outFile+                  exitFailure++  putStrLn $ "Successfully checked " ++ show (length allReplData) ++ " repl examples in " ++ latexFile opts++  return ()++  where p = info (optsParser <**> helper)+            ( fullDesc+              <> progDesc "Test the exercises in a cryptol LaTeX file"+              <> header "check-exercises -- test cryptol exercises"+            )
cryptol/Main.hs view
@@ -26,7 +26,6 @@ import Cryptol.Version (displayVersion)  import Control.Monad (when)-import Data.Maybe (isJust) import GHC.IO.Encoding (setLocaleEncoding, utf8) import System.Console.GetOpt     (OptDescr(..),ArgOrder(..),ArgDescr(..),getOpt,usageInfo)@@ -47,7 +46,8 @@   { optLoad            :: [FilePath]   , optVersion         :: Bool   , optHelp            :: Bool-  , optBatch           :: Maybe FilePath+  , optBatch           :: ReplMode+  , optCallStacks      :: Bool   , optCommands        :: [String]   , optColorMode       :: ColorMode   , optCryptolrc       :: Cryptolrc@@ -61,7 +61,8 @@   { optLoad            = []   , optVersion         = False   , optHelp            = False-  , optBatch           = Nothing+  , optBatch           = InteractiveRepl+  , optCallStacks      = True   , optCommands        = []   , optColorMode       = AutoColor   , optCryptolrc       = CryrcDefault@@ -75,6 +76,9 @@   [ Option "b" ["batch"] (ReqArg setBatchScript "FILE")     "run the script provided and exit" +  , Option "" ["interactive-batch"] (ReqArg setInteractiveBatchScript "FILE")+    "run the script provided and exit, but behave as if running an interactive session"+   , Option "e" ["stop-on-error"] (NoArg setStopOnError)     "stop script execution as soon as an error occurs." @@ -95,6 +99,9 @@   , Option "h" ["help"] (NoArg setHelp)     "display this message" +  , Option "" ["no-call-stacks"] (NoArg setNoCallStacks)+    "Disable tracking of call stack information, which reduces interpreter overhead"+   , Option "" ["no-unicode-logo"] (NoArg setNoUnicodeLogo)     "Don't use unicode characters in the REPL logo" @@ -124,8 +131,12 @@  -- | Set a batch script to be run. setBatchScript :: String -> OptParser Options-setBatchScript path = modify $ \ opts -> opts { optBatch = Just path }+setBatchScript path = modify $ \ opts -> opts { optBatch = Batch path } +-- | Set an interactive batch script+setInteractiveBatchScript :: String -> OptParser Options+setInteractiveBatchScript path = modify $ \ opts -> opts { optBatch = InteractiveBatch path }+ -- | Set the color mode of the terminal output. setColorMode :: String -> OptParser Options setColorMode "auto"   = modify $ \ opts -> opts { optColorMode = AutoColor }@@ -149,6 +160,10 @@ setCryrcDisabled :: OptParser Options setCryrcDisabled  = modify $ \ opts -> opts { optCryptolrc = CryrcDisabled } +-- | Disable call stack tracking+setNoCallStacks :: OptParser Options+setNoCallStacks = modify $ \opts -> opts { optCallStacks = False }+ -- | Add another file to read as a @.cryptolrc@ file, unless @.cryptolrc@ -- files have been disabled addCryrc :: String -> OptParser Options@@ -180,9 +195,15 @@             , "addition to the default locations"             ]           )+        , ( "EDITOR"+          , [ "Sets the editor executable to use when opening an editor"+            , "via the `:edit` command"+            ]+          )         , ( "SBV_{ABC,BOOLECTOR,CVC4,MATHSAT,YICES,Z3}_OPTIONS"           , [ "A string of command-line arguments to be passed to the"             , "corresponding solver invoked for `:sat` and `:prove`"+            , "when using a prover via SBV"             ]           )         ]@@ -206,6 +227,7 @@           (opts', mCleanup) <- setupCmdScript opts           status <- repl (optCryptolrc opts')                          (optBatch opts')+                         (optCallStacks opts')                          (optStopOnError opts')                          (setupREPL opts')           case mCleanup of@@ -225,9 +247,9 @@       (path, h) <- openTempFile tmpdir "cmds.icry"       hPutStr h (unlines cmds)       hClose h-      when (isJust (optBatch opts)) $+      when (optBatch opts /= InteractiveRepl) $         putStrLn "[warning] --command argument specified; ignoring batch file"-      return (opts { optBatch = Just path }, Just path)+      return (opts { optBatch = InteractiveBatch path }, Just path)  setupREPL :: Options -> REPL () setupREPL opts = do@@ -261,9 +283,10 @@   setUpdateREPLTitle (shouldSetREPLTitle >>= \b -> when b setREPLTitle)   updateREPLTitle   case optBatch opts of-    Nothing -> return ()     -- add the directory containing the batch file to the module search path-    Just file -> prependSearchPath [ takeDirectory file ]+    Batch file -> prependSearchPath [ takeDirectory file ]+    _ -> return ()+   case optLoad opts of     []  -> loadPrelude `REPL.catch` \x -> io $ print $ pp x     [l] -> loadCmd l `REPL.catch` \x -> do
cryptol/REPL/Haskeline.hs view
@@ -29,7 +29,6 @@ import           Data.Char (isAlphaNum, isSpace) import           Data.Function (on) import           Data.List (isPrefixOf,nub,sortBy,sort)-import           Data.Maybe(isJust) import qualified Data.Set as Set import qualified Data.Text as T (unpack) import           System.Console.ANSI (setTitle, hSupportsANSI)@@ -44,42 +43,57 @@ import           Prelude.Compat  +data ReplMode+  = InteractiveRepl -- ^ Interactive terminal session+  | Batch FilePath  -- ^ Execute from a batch file+  | InteractiveBatch FilePath+     -- ^ Execute from a batch file, but behave as though+     --   lines are entered in an interactive session.+ deriving (Show, Eq)+ -- | One REPL invocation, either from a file or from the terminal.-crySession :: Maybe FilePath -> Bool -> REPL CommandExitCode-crySession mbBatch stopOnError =+crySession :: ReplMode -> Bool -> REPL CommandExitCode+crySession replMode stopOnError =   do settings <- io (setHistoryFile (replSettings isBatch))-     let act = runInputTBehavior behavior settings (withInterrupt loop)+     let act = runInputTBehavior behavior settings (withInterrupt (loop 1))      if isBatch then asBatch act else act   where-  (isBatch,behavior) = case mbBatch of-    Nothing   -> (False,defaultBehavior)-    Just path -> (True,useFile path)+  (isBatch,behavior) = case replMode of+    InteractiveRepl       -> (False, defaultBehavior)+    Batch path            -> (True,  useFile path)+    InteractiveBatch path -> (False, useFile path) -  loop :: InputT REPL CommandExitCode-  loop =+  loop :: Int -> InputT REPL CommandExitCode+  loop lineNum =     do ln <- getInputLines =<< MTL.lift getPrompt        case ln of          NoMoreLines -> return CommandOk          Interrupted            | isBatch && stopOnError -> return CommandError-           | otherwise -> loop-         NextLine line-           | all isSpace line -> loop-           | otherwise        -> doCommand line+           | otherwise -> loop lineNum+         NextLine ls+           | all (all isSpace) ls -> loop (lineNum + length ls)+           | otherwise            -> doCommand lineNum ls -  doCommand txt =-    case parseCommand findCommandExact txt of-      Nothing | isBatch && stopOnError  -> return CommandError-              | otherwise -> loop -- say somtething?+  run lineNum cmd =+    case replMode of+      InteractiveRepl    -> runCommand lineNum Nothing cmd+      InteractiveBatch _ -> runCommand lineNum Nothing cmd+      Batch path         -> runCommand lineNum (Just path) cmd++  doCommand lineNum txt =+    case parseCommand findCommandExact (unlines txt) of+      Nothing | isBatch && stopOnError -> return CommandError+              | otherwise -> loop (lineNum + length txt)  -- say somtething?       Just cmd -> join $ MTL.lift $-        do status <- handleInterrupt (handleCtrlC CommandError) (runCommand cmd)+        do status <- handleInterrupt (handleCtrlC CommandError) (run lineNum cmd)            case status of              CommandError | isBatch && stopOnError -> return (return status)              _ -> do goOn <- shouldContinue-                     return (if goOn then loop else return status)+                     return (if goOn then loop (lineNum + length txt) else return status)  -data NextLine = NextLine String | NoMoreLines | Interrupted+data NextLine = NextLine [String] | NoMoreLines | Interrupted  getInputLines :: String -> InputT REPL NextLine getInputLines = handleInterrupt (MTL.lift (handleCtrlC Interrupted)) . loop []@@ -91,7 +105,7 @@          Nothing -> return NoMoreLines          Just l            | not (null l) && last l == '\\' -> loop (init l : ls) newPropmpt-           | otherwise -> return $ NextLine $ unlines $ reverse $ l : ls+           | otherwise -> return $ NextLine $ reverse $ l : ls  loadCryRC :: Cryptolrc -> REPL CommandExitCode loadCryRC cryrc =@@ -106,25 +120,32 @@        let file = dir </> ".cryptolrc"        present <- io (doesFileExist file)        if present-         then crySession (Just file) True+         then crySession (Batch file) True          else check others    loadMany []       = return CommandOk-  loadMany (f : fs) = do status <- crySession (Just f) True+  loadMany (f : fs) = do status <- crySession (Batch f) True                          case status of                            CommandOk -> loadMany fs                            _         -> return status  -- | Haskeline-specific repl implementation.-repl :: Cryptolrc -> Maybe FilePath -> Bool -> REPL () -> IO CommandExitCode-repl cryrc mbBatch stopOnError begin =-  runREPL (isJust mbBatch) stdoutLogger $-  do status <- loadCryRC cryrc-     case status of-       CommandOk -> begin >> crySession mbBatch stopOnError-       _         -> return status+repl :: Cryptolrc -> ReplMode -> Bool -> Bool -> REPL () -> IO CommandExitCode+repl cryrc replMode callStacks stopOnError begin =+  runREPL isBatch callStacks stdoutLogger replAction + where+  -- this flag is used to suppress the logo and prompts+  isBatch = case replMode of+              InteractiveRepl -> False+              Batch _ -> True+              InteractiveBatch _ -> True +  replAction =+    do status <- loadCryRC cryrc+       case status of+         CommandOk -> begin >> crySession replMode stopOnError+         _         -> return status  -- | Try to set the history file. setHistoryFile :: Settings REPL -> IO (Settings REPL)@@ -201,7 +222,7 @@ cryptolCommand :: CompletionFunc REPL cryptolCommand cursor@(l,r)   | ":" `isPrefixOf` l'-  , Just (cmd,rest) <- splitCommand l' = case nub (findCommand cmd) of+  , Just (_,cmd,rest) <- splitCommand l' = case nub (findCommand cmd) of        [c] | null rest && not (any isSpace l') -> do             return (l, cmdComp cmd c)
cryptol/REPL/Logo.hs view
@@ -14,6 +14,8 @@ import Cryptol.Version (commitShortHash,commitDirty) import Data.Version (showVersion) import System.Console.ANSI+import Prelude ()+import Prelude.Compat   type Version = String
lib/Cryptol.cry view
@@ -168,6 +168,13 @@ primitive type Literal : # -> * -> Prop  /**+ * 'LiteralLessThan n a' asserts that the type 'a' contains all the+ * natural numbers strictly below 'n'.  Note that we may have 'n = inf',+ * in which case the type 'a' must be unbounded.+ */+primitive type LiteralLessThan : # -> * -> Prop++/**  * The value corresponding to a numeric type.  */ primitive number : {val, rep} Literal val rep => rep@@ -195,6 +202,15 @@                                     [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.+ */+primitive fromToLessThan :+  {first, bound, a} (fin first, bound >= first, LiteralLessThan bound a) => [bound - first]a+++/**  * A finite arithmetic sequence starting with 'first' and 'next',  * stopping when the values reach or would skip over 'last'.  *@@ -879,8 +895,8 @@  * Declarations of the form 'x @ i = e' are syntactic sugar for  * 'x = generate (\i -> e)'.  */-generate : {n, a, ix} (fin n, n >= 1, Integral ix, Literal (n-1) ix) => (ix -> a) -> [n]a-generate f = [ f i | i <- [0 .. n-1] ]+generate : {n, a, ix} (Integral ix, LiteralLessThan n ix) => (ix -> a) -> [n]a+generate f = [ f i | i <- [0 .. <n] ]   // GF_2^n polynomial computations -------------------------------------------
lib/Float.cry view
@@ -79,6 +79,7 @@ primitive   fpPosInf : {e,p} ValidFloat e p => Float e p +/** Negative infinity. */ fpNegInf : {e,p} ValidFloat e p => Float e p fpNegInf = - fpPosInf @@ -133,13 +134,33 @@  infix 20 =.= +/** Test if this value is not-a-number (NaN). */+primitive fpIsNaN : {e,p} ValidFloat e p => Float e p -> Bool -/* Returns true for numbers that are not an infinity or NaN. */-primitive-  fpIsFinite : {e,p} ValidFloat e p => Float e p -> Bool+/** Test if this value is positive or negative infinity. */+primitive fpIsInf : {e,p} ValidFloat e p => Float e p -> Bool +/** Test if this value is positive or negative zero. */+primitive fpIsZero : {e,p} ValidFloat e p => Float e p -> Bool +/** Test if this value is negative. */+primitive fpIsNeg : {e,p} ValidFloat e p => Float e p -> Bool +/** Test if this value is normal (not NaN, not infinite, not zero, and not subnormal). */+primitive fpIsNormal : {e,p} ValidFloat e p => Float e p -> Bool++/**+ * Test if this value is subnormal.  Subnormal values are nonzero+ * values with magnitudes smaller than can be represented with the+ * normal implicit leading bit convention.+ */+primitive fpIsSubnormal : {e,p} ValidFloat e p => Float e p -> Bool++/* Returns true for numbers that are not an infinity or NaN. */+fpIsFinite : {e,p} ValidFloat e p => Float e p -> Bool+fpIsFinite f = ~ (fpIsNaN f \/ fpIsInf f )++ /* ----------------------------------------------------------------------  * Arithmetic  * ---------------------------------------------------------------------- */@@ -165,7 +186,31 @@   fpDiv : {e,p} ValidFloat e p =>     RoundingMode -> Float e p -> Float e p -> Float e p +/**+ * Fused-multiply-add.  'fpFMA r x y z' computes the value '(x*y)+z',+ * rounding the result according to mode 'r' only after performing both+ * operations.+ */+primitive+  fpFMA : {e,p} ValidFloat e p =>+    RoundingMode -> Float e p -> Float e p -> Float e p -> Float e p +/**+ * Absolute value of a floating-point value.+ */+primitive+  fpAbs : {e,p} ValidFloat e p =>+    Float e p -> Float e p++/**+ * Square root of a floating-point value.  The square root of+ * a negative value yiels NaN, except that the sqaure root of+ * '-0.0' is '-0.0'.+ */+primitive+  fpSqrt : {e,p} ValidFloat e p =>+    RoundingMode -> Float e p -> Float e p+ /* ------------------------------------------------------------ *  * Rationals                                                    *  * ------------------------------------------------------------ */@@ -181,4 +226,3 @@ primitive   fpFromRational : {e,p} ValidFloat e p =>     RoundingMode -> Rational -> Float e p-
src/Cryptol/Backend.hs view
@@ -27,39 +27,32 @@   , rationalLessThan   , rationalGreaterThan   , iteRational-  , ppRational   ) where  import Control.Monad.IO.Class import Data.Kind (Type)-import Data.Ratio ( (%), numerator, denominator )  import Cryptol.Backend.FloatHelpers (BF)-import Cryptol.Backend.Monad ( PPOpts(..), EvalError(..) )-import Cryptol.TypeCheck.AST(Name)-import Cryptol.Utils.PP-+import Cryptol.Backend.Monad+  ( EvalError(..), CallStack, pushCallFrame )+import Cryptol.ModuleSystem.Name(Name)+import Cryptol.Parser.Position  invalidIndex :: Backend sym => sym -> Integer -> SEval sym a-invalidIndex sym = raiseError sym . InvalidIndex . Just+invalidIndex sym i = raiseError sym (InvalidIndex (Just i))  cryUserError :: Backend sym => sym -> String -> SEval sym a-cryUserError sym = raiseError sym . UserError+cryUserError sym msg = raiseError sym (UserError msg)  cryNoPrimError :: Backend sym => sym -> Name -> SEval sym a-cryNoPrimError sym = raiseError sym . NoPrim-+cryNoPrimError sym nm = raiseError sym (NoPrim nm)  {-# INLINE sDelay #-} -- | Delay the given evaluation computation, returning a thunk --   which will run the computation when forced.  Raise a loop --   error if the resulting thunk is forced during its own evaluation.-sDelay :: Backend sym => sym -> Maybe String -> SEval sym a -> SEval sym (SEval sym a)-sDelay sym msg m =-  let msg'  = maybe "" ("while evaluating "++) msg-      retry = raiseError sym (LoopError msg')-   in sDelayFill sym m retry-+sDelay :: Backend sym => sym -> SEval sym a -> SEval sym (SEval sym a)+sDelay sym m = sDelayFill sym m Nothing ""  -- | Representation of rational numbers. --     Invariant: denominator is not 0@@ -198,16 +191,6 @@ iteRational sym p (SRational a b) (SRational c d) =   SRational <$> iteInteger sym p a c <*> iteInteger sym p b d -ppRational :: Backend sym => sym -> PPOpts -> SRational sym -> Doc-ppRational sym opts (SRational n d)-  | Just ni <- integerAsLit sym n-  , Just di <- integerAsLit sym d-  = let q = ni % di in-      text "(ratio" <+> integer (numerator q) <+> (integer (denominator q) <> text ")")--  | otherwise-  = text "(ratio" <+> ppInteger sym opts n <+> (ppInteger sym opts d <> text ")")- -- | 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.@@ -234,13 +217,27 @@   --   which will run the computation when forced.  Run the 'retry'   --   computation instead if the resulting thunk is forced during   --   its own evaluation.-  sDelayFill :: sym -> SEval sym a -> SEval sym a -> SEval sym (SEval sym a)+  sDelayFill :: sym -> SEval sym a -> Maybe (SEval sym a) -> String -> SEval sym (SEval sym a)    -- | Begin evaluating the given computation eagerly in a separate thread   --   and return a thunk which will await the completion of the given computation   --   when forced.   sSpark :: sym -> SEval sym a -> SEval sym (SEval sym a) +  -- | Push a call frame on to the current call stack while evaluating the given action+  sPushFrame :: sym -> Name -> Range -> SEval sym a -> SEval sym a+  sPushFrame sym nm rng m = sModifyCallStack sym (pushCallFrame nm rng) m++  -- | Use the given call stack while evaluating the given action+  sWithCallStack :: sym -> CallStack -> SEval sym a -> SEval sym a+  sWithCallStack sym stk m = sModifyCallStack sym (\_ -> stk) m++  -- | Apply the given function to the current call stack while evaluating the given action+  sModifyCallStack :: sym -> (CallStack -> CallStack) -> SEval sym a -> SEval sym a++  -- | Retrieve the current evaluation call stack+  sGetCallStack :: sym -> SEval sym CallStack+   -- | Merge the two given computations according to the predicate.   mergeEval ::      sym ->@@ -257,21 +254,6 @@   -- | Indiciate that an error condition exists   raiseError :: sym -> EvalError -> SEval sym a --  -- ==== Pretty printing  ====-  -- | Pretty-print an individual bit-  ppBit :: sym -> SBit sym -> Doc--  -- | Pretty-print a word value-  ppWord :: sym -> PPOpts -> SWord sym -> Doc--  -- | Pretty-print an integer value-  ppInteger :: sym -> PPOpts -> SInteger sym -> Doc--  -- | Pretty-print a floating-point value-  ppFloat :: sym -> PPOpts -> SFloat sym -> Doc--   -- ==== Identifying literal values ====    -- | Determine if this symbolic bit is a boolean literal@@ -291,6 +273,9 @@   -- | Determine if this symbolic integer is a literal   integerAsLit :: sym -> SInteger sym -> Maybe Integer +  -- | Determine if this symbolic floating-point value is a literal+  fpAsLit :: sym -> SFloat sym -> Maybe BF+   -- ==== Creating literal values ====    -- | Construct a literal bit value from a boolean.@@ -325,6 +310,7 @@   iteBit :: sym -> SBit sym -> SBit sym -> SBit sym -> SEval sym (SBit sym)   iteWord :: sym -> SBit sym -> SWord sym -> SWord sym -> SEval sym (SWord sym)   iteInteger :: sym -> SBit sym -> SInteger sym -> SInteger sym -> SEval sym (SInteger sym)+  iteFloat :: sym -> SBit sym -> SFloat sym -> SFloat sym -> SEval sym (SFloat sym)    -- ==== Bit operations ====   bitEq  :: sym -> SBit sym -> SBit sym -> SEval sym (SBit sym)@@ -333,7 +319,6 @@   bitXor :: sym -> SBit sym -> SBit sym -> SEval sym (SBit sym)   bitComplement :: sym -> SBit sym -> SEval sym (SBit sym) -   -- ==== Word operations ====    -- | Extract the numbered bit from the word.@@ -674,7 +659,7 @@     SInteger sym ->     SEval sym (SBit sym) -  -- | Multiplicitive inverse in (Z n).+  -- | Multiplicative inverse in (Z n).   --   PRECONDITION: the modulus is a prime   znRecip ::     sym ->@@ -689,21 +674,51 @@    fpLogicalEq   :: sym -> SFloat sym -> SFloat sym -> SEval sym (SBit sym) +  fpNaN    :: sym -> Integer {- ^ exponent bits -} -> Integer {- ^ precision bits -} -> SEval sym (SFloat sym)+  fpPosInf :: sym -> Integer {- ^ exponent bits -} -> Integer {- ^ precision bits -} -> SEval sym (SFloat sym)+   fpPlus, fpMinus, fpMult, fpDiv :: FPArith2 sym-  fpNeg :: sym -> SFloat sym -> SEval sym (SFloat sym)+  fpNeg, fpAbs :: sym -> SFloat sym -> SEval sym (SFloat sym)+  fpSqrt :: sym -> SWord sym -> SFloat sym -> SEval sym (SFloat sym) +  fpFMA :: sym -> SWord sym -> SFloat sym -> SFloat sym -> SFloat sym -> SEval sym (SFloat sym)++  fpIsZero, fpIsNeg, fpIsNaN, fpIsInf, fpIsNorm, fpIsSubnorm :: sym -> SFloat sym -> SEval sym (SBit sym)++  fpToBits :: sym -> SFloat sym -> SEval sym (SWord sym)+  fpFromBits ::+    sym ->+    Integer {- ^ exponent bits -} ->+    Integer {- ^ precision bits -} ->+    SWord sym ->+    SEval sym (SFloat sym)+   fpToInteger ::     sym ->     String {- ^ Name of the function for error reporting -} ->-    SWord sym {-^ Rounding mode -} ->-    SFloat sym -> SEval sym (SInteger sym)+    SWord sym {- ^ Rounding mode -} ->+    SFloat sym ->+    SEval sym (SInteger sym)    fpFromInteger ::     sym ->-    Integer         {- exp width -} ->-    Integer         {- prec width -} ->+    Integer         {- ^ exp width -} ->+    Integer         {- ^ prec width -} ->     SWord sym       {- ^ rounding mode -} ->-    SInteger sym    {- ^ the integeer to use -} ->+    SInteger sym    {- ^ the integer to use -} ->+    SEval sym (SFloat sym)++  fpToRational ::+    sym ->+    SFloat sym ->+    SEval sym (SRational sym)++  fpFromRational ::+    sym ->+    Integer         {- ^ exp width -} ->+    Integer         {- ^ prec width -} ->+    SWord sym       {- ^ rounding mode -} ->+    SRational sym ->     SEval sym (SFloat sym)  type FPArith2 sym =
src/Cryptol/Backend/Concrete.hs view
@@ -37,6 +37,7 @@  import qualified Control.Exception as X import Data.Bits+import Data.Ratio import Numeric (showIntAtBase) import qualified LibBF as FP import qualified GHC.Integer.GMP.Internals as Integer@@ -136,10 +137,12 @@   type SFloat Concrete = FP.BF   type SEval Concrete = Eval -  raiseError _ err = io (X.throwIO err)+  raiseError _ err =+    do stk <- getCallStack+       io (X.throwIO (EvalErrorEx stk err))    assertSideCondition _ True _ = return ()-  assertSideCondition _ False err = io (X.throwIO err)+  assertSideCondition sym False err = raiseError sym err    wordLen _ (BV w _) = w   wordAsChar _ (BV _ x) = Just $! integerToChar x@@ -160,15 +163,8 @@   sDeclareHole _ = blackhole   sDelayFill _ = delayFill   sSpark _ = evalSpark--  ppBit _ b | b         = text "True"-            | otherwise = text "False"--  ppWord _ = ppBV--  ppInteger _ _opts i = integer i--  ppFloat _ = FP.fpPP+  sModifyCallStack _ f m = modifyCallStack f m+  sGetCallStack _ = getCallStack    bitLit _ b = b   bitAsLit _ b = Just b@@ -182,6 +178,7 @@   iteBit _ b x y  = pure $! if b then x else y   iteWord _ b x y = pure $! if b then x else y   iteInteger _ b x y = pure $! if b then x else y+  iteFloat _ b x y   = pure $! if b then x else y    wordLit _ w i = pure $! mkBv w i   wordAsLit _ (BV w i) = Just (w,i)@@ -331,6 +328,11 @@   ------------------------------------------------------------------------   -- Floating Point   fpLit _sym e p rat     = pure (FP.fpLit e p rat)++  fpNaN _sym e p         = pure (FP.BF e p FP.bfNaN)+  fpPosInf _sym e p      = pure (FP.BF e p FP.bfPosInf)++  fpAsLit _ f            = Just f   fpExactLit _sym bf     = pure bf   fpEq _sym x y          = pure (FP.bfValue x == FP.bfValue y)   fpLogicalEq _sym x y   = pure (FP.bfCompare (FP.bfValue x) (FP.bfValue y) == EQ)@@ -340,17 +342,51 @@   fpMinus = fpBinArith FP.bfSub   fpMult  = fpBinArith FP.bfMul   fpDiv   = fpBinArith FP.bfDiv-  fpNeg _ x = pure x { FP.bfValue = FP.bfNeg (FP.bfValue x) }+  fpNeg _ x = pure $! x { FP.bfValue = FP.bfNeg (FP.bfValue x) }++  fpAbs _ x = pure $! x { FP.bfValue = FP.bfAbs (FP.bfValue x) }+  fpSqrt sym r x =+    do r' <- fpRoundMode sym r+       let opts = FP.fpOpts (FP.bfExpWidth x) (FP.bfPrecWidth x) r'+       pure $! x{ FP.bfValue = FP.fpCheckStatus (FP.bfSqrt opts (FP.bfValue x)) }++  fpFMA sym r x y z =+    do r' <- fpRoundMode sym r+       let opts = FP.fpOpts (FP.bfExpWidth x) (FP.bfPrecWidth x) r'+       pure $! x { FP.bfValue = FP.fpCheckStatus (FP.bfFMA opts (FP.bfValue x) (FP.bfValue y) (FP.bfValue z)) }++  fpIsZero _ x = pure (FP.bfIsZero (FP.bfValue x))+  fpIsNeg _ x  = pure (FP.bfIsNeg (FP.bfValue x))+  fpIsNaN _ x  = pure (FP.bfIsNaN (FP.bfValue x))+  fpIsInf _ x  = pure (FP.bfIsInf (FP.bfValue x))+  fpIsNorm _ x =+    let opts = FP.fpOpts (FP.bfExpWidth x) (FP.bfPrecWidth x) FP.NearEven+     in pure (FP.bfIsNormal opts (FP.bfValue x))+  fpIsSubnorm _ x =+    let opts = FP.fpOpts (FP.bfExpWidth x) (FP.bfPrecWidth x) FP.NearEven+     in pure (FP.bfIsSubnormal opts (FP.bfValue x))++  fpFromBits _sym e p bv = pure (FP.floatFromBits e p (bvVal bv))+  fpToBits _sym (FP.BF e p v) = pure (mkBv (e+p) (FP.floatToBits e p v))+   fpFromInteger sym e p r x =-    do opts <- FP.fpOpts e p <$> fpRoundMode sym r+    do r' <- fpRoundMode sym r        pure FP.BF { FP.bfExpWidth = e                   , FP.bfPrecWidth = p                   , FP.bfValue = FP.fpCheckStatus $-                                 FP.bfRoundInt opts (FP.bfFromInteger x)+                                 FP.bfRoundInt r' (FP.bfFromInteger x)                   }   fpToInteger = fpCvtToInteger +  fpFromRational sym e p r x =+    do mode <- fpRoundMode sym r+       pure (FP.floatFromRational e p mode (sNum x % sDenom x)) +  fpToRational sym fp =+      case FP.floatToRational "fpToRational" fp of+        Left err -> raiseError sym err+        Right r  -> pure $ SRational { sNum = numerator r, sDenom = denominator r }+ {-# INLINE liftBinIntMod #-} liftBinIntMod :: Monad m =>   (Integer -> Integer -> Integer) -> Integer -> Integer -> Integer -> m Integer@@ -371,7 +407,7 @@ fpBinArith fun = \sym r x y ->   do opts <- FP.fpOpts (FP.bfExpWidth x) (FP.bfPrecWidth x)                                                   <$> fpRoundMode sym r-     pure x { FP.bfValue = FP.fpCheckStatus+     pure $! x { FP.bfValue = FP.fpCheckStatus                                 (fun opts (FP.bfValue x) (FP.bfValue y)) }  fpCvtToInteger ::@@ -391,8 +427,3 @@   case FP.fpRound (bvVal w) of     Left err -> raiseError sym err     Right a  -> pure a-----
src/Cryptol/Backend/FloatHelpers.hs view
@@ -2,22 +2,19 @@ {-# Language BangPatterns #-} module Cryptol.Backend.FloatHelpers where +import Data.Char (isDigit) import Data.Ratio(numerator,denominator)-import Data.Int(Int64)-import Data.Bits(testBit,setBit,shiftL,shiftR,(.&.),(.|.)) import LibBF  import Cryptol.Utils.PP import Cryptol.Utils.Panic(panic)-import Cryptol.Backend.Monad( EvalError(..)-                         , PPOpts(..), PPFloatFormat(..), PPFloatExp(..)-                         )+import Cryptol.Backend.Monad( EvalError(..) )   data BF = BF-  { bfExpWidth  :: Integer-  , bfPrecWidth :: Integer-  , bfValue     :: BigFloat+  { bfExpWidth  :: !Integer+  , bfPrecWidth :: !Integer+  , bfValue     :: !BigFloat   }  @@ -86,19 +83,32 @@   str = bfToString base fmt num   fmt = addPrefix <> showRnd NearEven <>         case useFPFormat opts of-          FloatFree e -> withExp e $ showFreeMin+          FloatFree e -> withExp e $ showFree                                    $ Just $ fromInteger precW           FloatFixed n e -> withExp e $ showFixed $ fromIntegral n           FloatFrac n    -> showFrac $ fromIntegral n    -- non-base 10 literals are not overloaded so we add an explicit-  -- .0 if one is not present. +  -- .0 if one is not present.  Moreover, we trim any extra zeros+  -- that appear in a decimal representation.   hacStr-    | base == 10 || elem '.' str = str+    | base == 10   = trimZeros+    | elem '.' str = str     | otherwise = case break (== 'p') str of                     (xs,ys) -> xs ++ ".0" ++ ys +  trimZeros =+    case break (== '.') str of+      (xs,'.':ys) ->+        case break (not . isDigit) ys of+          (frac, suffix) -> xs ++ '.' : processFraction frac ++ suffix+      _ -> str +  processFraction frac =+    case dropWhile (== '0') (reverse frac) of+      [] -> "0"+      zs -> reverse zs+ -- | Make a literal fpLit ::   Integer     {- ^ Exponent width -} ->@@ -152,97 +162,17 @@                               ["Unexpected rounding mode", show r]  -- floatFromBits ::    Integer {- ^ Exponent width -} ->   Integer {- ^ Precision widht -} ->   Integer {- ^ Raw bits -} ->   BF-floatFromBits e p bv = BF { bfValue = floatFromBits' e p bv+floatFromBits e p bv = BF { bfValue = bfFromBits (fpOpts e p NearEven) bv                            , bfExpWidth = e, bfPrecWidth = p }  ---- | Make a float using "raw" bits.-floatFromBits' ::-  Integer {- ^ Exponent width -} ->-  Integer {- ^ Precision widht -} ->-  Integer {- ^ Raw bits -} ->-  BigFloat--floatFromBits' e p bits-  | expoBiased == 0 && mant == 0 =            -- zero-    if isNeg then bfNegZero else bfPosZero--  | expoBiased == eMask && mant ==  0 =       -- infinity-    if isNeg then bfNegInf else bfPosInf--  | expoBiased == eMask = bfNaN               -- NaN--  | expoBiased == 0 =                         -- Subnormal-    case bfMul2Exp opts (bfFromInteger mant) (expoVal + 1) of-      (num,Ok) -> if isNeg then bfNeg num else num-      (_,s)    -> panic "floatFromBits" [ "Unexpected status: " ++ show s ]--  | otherwise =                               -- Normal-    case bfMul2Exp opts (bfFromInteger mantVal) expoVal of-      (num,Ok) -> if isNeg then bfNeg num else num-      (_,s)    -> panic "floatFromBits" [ "Unexpected status: " ++ show s ]--  where-  opts       = expBits e' <> precBits (p' + 1) <> allowSubnormal--  e'         = fromInteger e                               :: Int-  p'         = fromInteger p - 1                           :: Int-  eMask      = (1 `shiftL` e') - 1                         :: Int64-  pMask      = (1 `shiftL` p') - 1                         :: Integer--  isNeg      = testBit bits (e' + p')--  mant       = pMask .&. bits                              :: Integer-  mantVal    = mant `setBit` p'                            :: Integer-  -- accounts for the implicit 1 bit--  expoBiased = eMask .&. fromInteger (bits `shiftR` p')    :: Int64-  bias       = eMask `shiftR` 1                            :: Int64-  expoVal    = expoBiased - bias - fromIntegral p'         :: Int64-- -- | Turn a float into raw bits. -- @NaN@ is represented as a positive "quiet" @NaN@ -- (most significant bit in the significand is set, the rest of it is 0) floatToBits :: Integer -> Integer -> BigFloat -> Integer-floatToBits e p bf =  (isNeg      `shiftL` (e' + p'))-                  .|. (expBiased  `shiftL` p')-                  .|. (mant       `shiftL` 0)-  where-  e' = fromInteger e     :: Int-  p' = fromInteger p - 1 :: Int--  eMask = (1 `shiftL` e') - 1   :: Integer-  pMask = (1 `shiftL` p') - 1   :: Integer--  (isNeg, expBiased, mant) =-    case bfToRep bf of-      BFNaN       -> (0,  eMask, 1 `shiftL` (p' - 1))-      BFRep s num -> (sign, be, ma)-        where-        sign = case s of-                Neg -> 1-                Pos -> 0--        (be,ma) =-          case num of-            Zero     -> (0,0)-            Num i ev-              | ex == 0   -> (0, i `shiftL` (p' - m  -1))-              | otherwise -> (ex, (i `shiftL` (p' - m)) .&. pMask)-              where-              m    = msb 0 i - 1-              bias = eMask `shiftR` 1-              ex   = toInteger ev + bias + toInteger m--            Inf -> (eMask,0)--  msb !n j = if j == 0 then n else msb (n+1) (j `shiftR` 1)+floatToBits e p bf = bfToBits (fpOpts e p NearEven) bf
src/Cryptol/Backend/Monad.hs view
@@ -1,6 +1,6 @@ -- |--- Module      :  Cryptol.Eval.Monad--- Copyright   :  (c) 2013-2016 Galois, Inc.+-- Module      :  Cryptol.Backend.Monad+-- Copyright   :  (c) 2013-2020 Galois, Inc. -- License     :  BSD3 -- Maintainer  :  cryptol@galois.com -- Stability   :  provisional@@ -16,80 +16,97 @@ ( -- * Evaluation monad   Eval(..) , runEval-, EvalOpts(..)-, PPOpts(..)-, asciiMode-, PPFloatFormat(..)-, PPFloatExp(..)-, defaultPPOpts , io , delayFill , ready , blackhole , evalSpark , maybeReady+  -- * Call stacks+, CallStack+, getCallStack+, withCallStack+, modifyCallStack+, combineCallStacks+, pushCallFrame+, displayCallStack   -- * Error reporting , Unsupported(..) , EvalError(..)+, EvalErrorEx(..) , evalPanic , wordTooWide-, typeCannotBeDemoted+, WordTooWide(..) ) where  import           Control.Concurrent import           Control.Concurrent.STM  import           Control.Monad-import qualified Control.Monad.Fail as Fail-import           Control.Monad.Fix import           Control.Monad.IO.Class+import           Data.Foldable (toList)+import           Data.Sequence (Seq)+import qualified Data.Sequence as Seq import           Data.Typeable (Typeable) import qualified Control.Exception as X  +import Cryptol.Parser.Position import Cryptol.Utils.Panic import Cryptol.Utils.PP-import Cryptol.Utils.Logger(Logger)-import Cryptol.TypeCheck.AST(Type,Name)+import Cryptol.TypeCheck.AST(Name)  -- | A computation that returns an already-evaluated value. ready :: a -> Eval a ready a = Ready a --- | How to pretty print things when evaluating-data PPOpts = PPOpts-  { useAscii     :: Bool-  , useBase      :: Int-  , useInfLength :: Int-  , useFPBase    :: Int-  , useFPFormat  :: PPFloatFormat-  } -asciiMode :: PPOpts -> Integer -> Bool-asciiMode opts width = useAscii opts && (width == 7 || width == 8)+-- | 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 PPFloatFormat =-    FloatFixed Int PPFloatExp -- ^ Use this many significant digis-  | FloatFrac Int             -- ^ Show this many digits after floating point-  | FloatFree PPFloatExp      -- ^ Use the correct number of digits+-- | 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+  where+  f (nm,rng)+    | rng == emptyRange = pp nm+    | otherwise = pp nm <+> text "called at" <+> pp rng -data PPFloatExp = ForceExponent -- ^ Always show an exponent-                | AutoExponent  -- ^ Only show exponent when needed +-- | Combine the call stack of a function value with the call+--   stack of the current calling context.  This algorithm is+--   the same one GHC uses to compute profiling calling contexts.+--+--   The algorithm is as follows.+--+--        ccs ++> ccsfn  =  ccs ++ dropCommonPrefix ccs ccsfn+--+--      where+--+--        dropCommonPrefix A B+--           -- returns the suffix of B after removing any prefix common+--           -- to both A and B.+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+  dropCommonPrefix (a Seq.:<| as) xs@(f Seq.:<| fs)+    | a == f    = dropCommonPrefix as fs+    | otherwise = xs -defaultPPOpts :: PPOpts-defaultPPOpts = PPOpts { useAscii = False, useBase = 10, useInfLength = 5-                       , useFPBase = 16-                       , useFPFormat = FloatFree AutoExponent-                       }+-- | Add a call frame to the top of a call stack+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)  --- | Some options for evalutaion-data EvalOpts = EvalOpts-  { evalLogger :: Logger    -- ^ Where to print stuff (e.g., for @trace@)-  , evalPPOpts :: PPOpts    -- ^ How to pretty print things.-  }- -- | The monad for Cryptol evaluation. --   A computation is either "ready", which means it represents --   only trivial computation, or is an "eval" action which must@@ -97,7 +114,7 @@ --   represents a delayed, shared computation. data Eval a    = Ready !a-   | Eval !(IO a)+   | Eval !(CallStack -> IO a)    | Thunk !(TVar (ThunkState a))  -- | This datastructure tracks the lifecycle of a thunk.@@ -107,7 +124,7 @@ --   cryptol expression that is bound to a name, and is not --   already obviously a value (and in a few other places as --   well) will get turned into a thunk in order to avoid---   recomputations.  These thunks will start in the `Unforced`+--   recomputation.  These thunks will start in the `Unforced` --   state, and have a backup computation that just raises --   the `LoopError` exception. --@@ -129,16 +146,20 @@ data ThunkState a   = Void !String        -- ^ This thunk has not yet been initialized-  | Unforced !(IO a) !(IO a)+  | Unforced !(IO a) !(Maybe (IO a)) !String !CallStack        -- ^ This thunk has not yet been forced.  We keep track of the "main"-       --   computation to run and a "backup" computation to run if we+       --   computation to run and an optional "backup" computation to run if we        --   detect a tight loop when evaluating the first one.-  | UnderEvaluation !ThreadId !(IO a)+       --   The final two arguments are used to throw a loop exception+       --   if the backup computation also causes a tight loop.+  | UnderEvaluation !ThreadId !(Maybe (IO a)) !String !CallStack        -- ^ This thunk is currently being evaluated by the thread with the given-       --   thread ID.  We track the "backup" computation to run if we detect+       --   thread ID.  We track an optional "backup" computation to run if we detect        --   a tight loop evaluating this thunk.  If the thunk is being evaluated        --   by some other thread, the current thread will await its completion.-  | ForcedErr !EvalError+       --   The final two arguments are used to throw a loop exception+       --   if the backup computation also causes a tight loop.+  | ForcedErr !EvalErrorEx        -- ^ This thunk has been forced, and its evaluation results in an exception   | Forced !a        -- ^ This thunk has been forced to the given value@@ -148,7 +169,7 @@ --   it requires no computation to return. maybeReady :: Eval a -> Eval (Maybe a) maybeReady (Ready a) = pure (Just a)-maybeReady (Thunk tv) = Eval $+maybeReady (Thunk tv) = Eval $ \_ ->   readTVarIO tv >>= \case      Forced a -> pure (Just a)      _ -> pure Nothing@@ -163,11 +184,13 @@ --   its own evaluation. delayFill ::   Eval a {- ^ Computation to delay -} ->-  Eval a {- ^ Backup computation to run if a tight loop is detected -} ->+  Maybe (Eval a) {- ^ Optional backup computation to run if a tight loop is detected -} ->+  String {- ^ message for the <<loop>> exception if a tight loop is detected -} ->   Eval (Eval a)-delayFill e@(Ready _) _  = return e-delayFill e@(Thunk _) _  = return e-delayFill (Eval x) backup = Eval (Thunk <$> newTVarIO (Unforced x (runEval backup)))+delayFill e@(Ready _) _ _ = return e+delayFill e@(Thunk _) _ _ = return e+delayFill (Eval x) backup msg =+  Eval (\stk -> Thunk <$> newTVarIO (Unforced (x stk) (runEval stk <$> backup) msg stk))  -- | Begin executing the given operation in a separate thread, --   returning a thunk which will await the completion of@@ -183,24 +206,24 @@ -- been forced.  If so, return the result.  Otherwise, -- fork a thread to force this computation and return -- the thunk.-evalSpark (Thunk tv)  = Eval $+evalSpark (Thunk tv)  = Eval $ \_stk ->   readTVarIO tv >>= \case     Forced x     -> return (Ready x)-    ForcedErr ex -> return (Eval (X.throwIO ex))+    ForcedErr ex -> return (Eval $ \_ -> (X.throwIO ex))     _ ->        do _ <- forkIO (sparkThunk tv)           return (Thunk tv)  -- If the computation is nontrivial but not already a thunk, -- create a thunk and fork a thread to force it.-evalSpark (Eval x) = Eval $-  do tv <- newTVarIO (Unforced x (X.throwIO (LoopError "")))+evalSpark (Eval x) = Eval $ \stk ->+  do tv <- newTVarIO (Unforced (x stk) Nothing "" stk)      _ <- forkIO (sparkThunk tv)      return (Thunk tv)   -- | To the work of forcing a thunk. This is the worker computation---   that is foked off via @evalSpark@.+--   that is forked off via @evalSpark@. sparkThunk :: TVar (ThunkState a) -> IO () sparkThunk tv =   do tid <- myThreadId@@ -212,13 +235,13 @@               do st <- readTVar tv                  case st of                    Void _ -> retry-                   Unforced _ backup -> writeTVar tv (UnderEvaluation tid backup)+                   Unforced _ backup msg stk -> writeTVar tv (UnderEvaluation tid backup msg stk)                    _ -> return ()                  return st      -- If we successfully claimed the thunk to work on, run the computation and      -- update the thunk state with the result.      case st of-       Unforced work _ ->+       Unforced work _ _ _ ->          X.try work >>= \case            Left err -> atomically (writeTVar tv (ForcedErr err))            Right a  -> atomically (writeTVar tv (Forced a))@@ -232,10 +255,10 @@ blackhole ::   String {- ^ A name to associate with this thunk. -} ->   Eval (Eval a, Eval a -> Eval ())-blackhole msg = Eval $+blackhole msg = Eval $ \stk ->   do tv <- newTVarIO (Void msg)      let set (Ready x)  = io $ atomically (writeTVar tv (Forced x))-         set m          = io $ atomically (writeTVar tv (Unforced (runEval m) (X.throwIO (LoopError msg))))+         set m          = io $ atomically (writeTVar tv (Unforced (runEval stk m) Nothing msg stk))      return (Thunk tv, set)  -- | Force a thunk to get the result.@@ -254,16 +277,19 @@                   case res of                     -- In this case, we claim the thunk.  Update the state to indicate                     -- that we are working on it.-                    Unforced _ backup -> writeTVar tv (UnderEvaluation tid backup)+                    Unforced _ backup msg stk -> writeTVar tv (UnderEvaluation tid backup msg stk)                      -- In this case, the thunk is already being evaluated.  If it is                     -- under evaluation by this thread, we have to run the backup computation,                     -- and "consume" it by updating the backup computation to one that throws                     -- a loop error.  If some other thread is evaluating, reset the                     -- transaction to await completion of the thunk.-                    UnderEvaluation t _-                      | tid == t  -> writeTVar tv (UnderEvaluation tid (X.throwIO (LoopError "")))-                      | otherwise -> retry -- wait, if some other thread is evaualting+                    UnderEvaluation t backup msg stk+                      | tid == t  ->+                          case backup of+                            Just _  -> writeTVar tv (UnderEvaluation tid Nothing msg stk)+                            Nothing -> writeTVar tv (ForcedErr (EvalErrorEx stk (LoopError msg)))+                      | otherwise -> retry -- wait, if some other thread is evaluating                     _ -> return ()                    -- Return the original thunk state so we can decide what work to do@@ -283,25 +309,43 @@            Void msg -> evalPanic "unDelay" ["Thunk forced before it was initialized", msg]            Forced x -> pure x            ForcedErr e -> X.throwIO e-           UnderEvaluation _ backup -> doWork backup -- this thread was already evaluating this thunk-           Unforced work _ -> doWork work+           -- this thread was already evaluating this thunk+           UnderEvaluation _ (Just backup) _ _ -> doWork backup+           UnderEvaluation _ Nothing msg stk -> X.throwIO (EvalErrorEx stk (LoopError msg))+           Unforced work _ _ _ -> doWork work +-- | Get the current call stack+getCallStack :: Eval CallStack+getCallStack = Eval (\stk -> pure stk)++-- | Execute the action with the given call stack+withCallStack :: CallStack -> Eval a -> Eval a+withCallStack stk m = Eval (\_ -> runEval stk m)++-- | Run the given action with a modify call stack+modifyCallStack :: (CallStack -> CallStack) -> Eval a -> Eval a+modifyCallStack f m =+  Eval $ \stk ->+    do let stk' = f stk+       -- putStrLn $ unwords ["Pushing call stack", show (displayCallStack stk')]+       runEval stk' m+ -- | Execute the given evaluation action.-runEval :: Eval a -> IO a-runEval (Ready a)  = return a-runEval (Eval x)   = x-runEval (Thunk tv) = unDelay tv+runEval :: CallStack -> Eval a -> IO a+runEval _   (Ready a)  = return a+runEval stk (Eval x)   = x stk+runEval _   (Thunk tv) = unDelay tv  {-# INLINE evalBind #-} evalBind :: Eval a -> (a -> Eval b) -> Eval b evalBind (Ready a) f  = f a-evalBind (Eval x) f   = Eval (x >>= runEval . f)-evalBind (Thunk x) f  = Eval (unDelay x >>= runEval . f)+evalBind (Eval x)  f  = Eval (\stk -> x stk >>= runEval stk . f)+evalBind (Thunk x) f  = Eval (\stk -> unDelay x >>= runEval stk . f)  instance Functor Eval where   fmap f (Ready x)   = Ready (f x)-  fmap f (Eval m)    = Eval (f <$> m)-  fmap f (Thunk tv)  = Eval (f <$> unDelay tv)+  fmap f (Eval m)    = Eval (\stk -> f <$> m stk)+  fmap f (Thunk tv)  = Eval (\_   -> f <$> unDelay tv)   {-# INLINE fmap #-}  instance Applicative Eval where@@ -316,18 +360,12 @@   {-# INLINE return #-}   {-# INLINE (>>=) #-} -instance Fail.MonadFail Eval where-  fail x = Eval (fail x)- instance MonadIO Eval where   liftIO = io -instance MonadFix Eval where-  mfix f = Eval $ mfix (\x -> runEval (f x))- -- | Lift an 'IO' computation into the 'Eval' monad. io :: IO a -> Eval a-io m = Eval m+io m = Eval (\_stk -> m) {-# INLINE io #-}  @@ -341,37 +379,53 @@ -- | Data type describing errors that can occur during evaluation. data EvalError   = InvalidIndex (Maybe Integer)  -- ^ Out-of-bounds index-  | TypeCannotBeDemoted Type      -- ^ Non-numeric type passed to @number@ function   | DivideByZero                  -- ^ Division or modulus by 0   | NegativeExponent              -- ^ Exponentiation by negative integer   | LogNegative                   -- ^ Logarithm of a negative integer-  | WordTooWide Integer           -- ^ Bitvector too large   | UserError String              -- ^ Call to the Cryptol @error@ primitive   | LoopError String              -- ^ Detectable nontermination   | NoPrim Name                   -- ^ Primitive with no implementation   | BadRoundingMode Integer       -- ^ Invalid rounding mode   | BadValue String               -- ^ Value outside the domain of a partial function.-    deriving (Typeable,Show)+    deriving Typeable  instance PP EvalError where   ppPrec _ e = case e of     InvalidIndex (Just i) -> text "invalid sequence index:" <+> integer i     InvalidIndex Nothing  -> text "invalid sequence index"-    TypeCannotBeDemoted t -> text "type cannot be demoted:" <+> pp t     DivideByZero -> text "division by 0"     NegativeExponent -> text "negative exponent"     LogNegative -> text "logarithm of negative"-    WordTooWide w ->-      text "word too wide for memory:" <+> integer w <+> text "bits"     UserError x -> text "Run-time error:" <+> text x-    LoopError x -> text "<<loop>>" <+> text x+    LoopError x -> vcat [ text "<<loop>>" <+> text x+                        , text "This usually occurs due to an improper recursive definition,"+                        , text "but may also result from retrying a previously interrupted"+                        , text "computation (e.g., after CTRL^C). In that case, you may need to"+                        , text "`:reload` the current module to reset to a good state."+                        ]     BadRoundingMode r -> "invalid rounding mode" <+> integer r     BadValue x -> "invalid input for" <+> backticks (text x)     NoPrim x -> text "unimplemented primitive:" <+> pp x -instance X.Exception EvalError+instance Show EvalError where+  show = show . pp +data EvalErrorEx =+  EvalErrorEx CallStack EvalError+ deriving Typeable +instance PP EvalErrorEx where+  ppPrec _ (EvalErrorEx stk ex) = vcat ([ pp ex ] ++ callStk)++   where+    callStk | Seq.null stk = []+            | otherwise = [ text "-- Backtrace --", displayCallStack stk ]++instance Show EvalErrorEx where+  show = show . pp++instance X.Exception EvalErrorEx+ data Unsupported   = UnsupportedSymbolicOp String  -- ^ Operation cannot be supported in the symbolic simulator     deriving (Typeable,Show)@@ -382,13 +436,20 @@  instance X.Exception Unsupported ---- | For things like @`(inf)@ or @`(0-1)@.-typeCannotBeDemoted :: Type -> a-typeCannotBeDemoted t = X.throw (TypeCannotBeDemoted t)- -- | For when we know that a word is too wide and will exceed gmp's -- limits (though words approaching this size will probably cause the -- system to crash anyway due to lack of memory). wordTooWide :: Integer -> a wordTooWide w = X.throw (WordTooWide w)++data WordTooWide = WordTooWide Integer -- ^ Bitvector too large+ deriving Typeable++instance PP WordTooWide where+  ppPrec _ (WordTooWide w) =+      text "word too wide for memory:" <+> integer w <+> text "bits"++instance Show WordTooWide where+  show = show . pp++instance X.Exception WordTooWide
src/Cryptol/Backend/SBV.hs view
@@ -6,6 +6,7 @@ -- Stability   :  provisional -- Portability :  portable +{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -43,14 +44,14 @@ import qualified Data.SBV.Internals as SBV  import Cryptol.Backend-import Cryptol.Backend.Concrete ( integerToChar, ppBV, BV(..) )+import Cryptol.Backend.Concrete ( integerToChar ) import Cryptol.Backend.Monad   ( Eval(..), blackhole, delayFill, evalSpark-  , EvalError(..), Unsupported(..)+  , EvalError(..), EvalErrorEx(..), Unsupported(..)+  , modifyCallStack, getCallStack   )  import Cryptol.Utils.Panic (panic)-import Cryptol.Utils.PP  data SBV =   SBV@@ -73,23 +74,30 @@ literalSWord :: Int -> Integer -> SWord SBV literalSWord w i = svInteger (KBounded False w) i +svMkSymVar_ :: Maybe Quantifier -> Kind -> Maybe String -> SBV.State -> IO SVal+#if MIN_VERSION_sbv(8,8,0)+svMkSymVar_ = svMkSymVar . SBV.NonQueryVar+#else+svMkSymVar_ = svMkSymVar+#endif+ freshBV_ :: SBV -> Int -> IO (SWord SBV) freshBV_ (SBV stateVar _) w =-  withMVar stateVar (svMkSymVar Nothing (KBounded False w) Nothing)+  withMVar stateVar (svMkSymVar_ Nothing (KBounded False w) Nothing)  freshSBool_ :: SBV -> IO (SBit SBV) freshSBool_ (SBV stateVar _) =-  withMVar stateVar (svMkSymVar Nothing KBool Nothing)+  withMVar stateVar (svMkSymVar_ Nothing KBool Nothing)  freshSInteger_ :: SBV -> IO (SInteger SBV) freshSInteger_ (SBV stateVar _) =-  withMVar stateVar (svMkSymVar Nothing KUnbounded Nothing)+  withMVar stateVar (svMkSymVar_ Nothing KUnbounded Nothing)   -- SBV Evaluation monad -------------------------------------------------------  data SBVResult a-  = SBVError !EvalError+  = SBVError !EvalErrorEx   | SBVResult !SVal !a -- safety predicate and result  instance Functor SBVResult where@@ -146,17 +154,19 @@   type SFloat SBV = ()        -- XXX: not implemented   type SEval SBV = SBVEval -  raiseError _ err = SBVEval (pure (SBVError err))+  raiseError _ err = SBVEval $+    do stk <- getCallStack+       pure (SBVError (EvalErrorEx stk err)) -  assertSideCondition _ cond err-    | Just False <- svAsBool cond = SBVEval (pure (SBVError err))+  assertSideCondition sym cond err+    | Just False <- svAsBool cond = raiseError sym err     | otherwise = SBVEval (pure (SBVResult cond ()))    isReady _ (SBVEval (Ready _)) = True   isReady _ _ = False -  sDelayFill _ m retry = SBVEval $-    do m' <- delayFill (sbvEval m) (sbvEval retry)+  sDelayFill _ m retry msg = SBVEval $+    do m' <- delayFill (sbvEval m) (sbvEval <$> retry) msg        pure (pure (SBVEval m'))    sSpark _ m = SBVEval $@@ -167,6 +177,11 @@     do (hole, fill) <- blackhole msg        pure (pure (SBVEval hole, \m -> SBVEval (fmap pure $ fill (sbvEval m)))) +  sModifyCallStack _ f (SBVEval m) = SBVEval $+    modifyCallStack f m++  sGetCallStack _ = SBVEval (pure <$> getCallStack)+   mergeEval _sym f c mx my = SBVEval $     do rx <- sbvEval mx        ry <- sbvEval my@@ -187,16 +202,6 @@   wordLen _ v = toInteger (intSizeOf v)   wordAsChar _ v = integerToChar <$> svAsInteger v -  ppBit _ v-     | Just b <- svAsBool v = text $! if b then "True" else "False"-     | otherwise            = text "?"-  ppWord sym opts v-     | Just x <- svAsInteger v = ppBV opts (BV (wordLen sym v) x)-     | otherwise               = text "[?]"-  ppInteger _ _opts v-     | Just x <- svAsInteger v = integer x-     | otherwise               = text "[?]"-   iteBit _ b x y = pure $! svSymbolicMerge KBool True b x y   iteWord _ b x y = pure $! svSymbolicMerge (kindOf x) True b x y   iteInteger _ b x y = pure $! svSymbolicMerge KUnbounded True b x y@@ -319,20 +324,37 @@   znNegate sym m a  = sModNegate sym m a   znRecip = sModRecip -  ppFloat _ _ _           = text "[?]"-  fpExactLit _ _          = unsupported "fpExactLit"-  fpLit _ _ _ _           = unsupported "fpLit"-  fpLogicalEq _ _ _       = unsupported "fpLogicalEq"-  fpEq _ _ _              = unsupported "fpEq"-  fpLessThan _ _ _        = unsupported "fpLessThan"-  fpGreaterThan _ _ _     = unsupported "fpGreaterThan"-  fpPlus _ _ _ _          = unsupported "fpPlus"-  fpMinus _ _ _ _         = unsupported "fpMinus"-  fpMult _  _ _ _         = unsupported "fpMult"-  fpDiv _ _ _ _           = unsupported "fpDiv"-  fpNeg _ _               = unsupported "fpNeg"-  fpFromInteger _ _ _ _ _ = unsupported "fpFromInteger"-  fpToInteger _ _ _ _     = unsupported "fpToInteger"+  fpAsLit _ _               = Nothing+  iteFloat _ _ _ _          = unsupported "iteFloat"+  fpNaN _ _ _               = unsupported "fpNaN"+  fpPosInf _ _ _            = unsupported "fpPosInf"+  fpExactLit _ _            = unsupported "fpExactLit"+  fpLit _ _ _ _             = unsupported "fpLit"+  fpLogicalEq _ _ _         = unsupported "fpLogicalEq"+  fpEq _ _ _                = unsupported "fpEq"+  fpLessThan _ _ _          = unsupported "fpLessThan"+  fpGreaterThan _ _ _       = unsupported "fpGreaterThan"+  fpPlus _ _ _ _            = unsupported "fpPlus"+  fpMinus _ _ _ _           = unsupported "fpMinus"+  fpMult _ _ _ _            = unsupported "fpMult"+  fpDiv _ _ _ _             = unsupported "fpDiv"+  fpAbs _ _                 = unsupported "fpAbs"+  fpSqrt _ _ _              = unsupported "fpSqrt"+  fpFMA _ _ _ _ _           = unsupported "fpFMA"+  fpNeg _ _                 = unsupported "fpNeg"+  fpFromInteger _ _ _ _ _   = unsupported "fpFromInteger"+  fpToInteger _ _ _ _       = unsupported "fpToInteger"+  fpIsZero _ _              = unsupported "fpIsZero"+  fpIsInf _ _               = unsupported "fpIsInf"+  fpIsNeg _ _               = unsupported "fpIsNeg"+  fpIsNaN _ _               = unsupported "fpIsNaN"+  fpIsNorm _ _              = unsupported "fpIsNorm"+  fpIsSubnorm _ _           = unsupported "fpIsSubnorm"+  fpToBits _ _              = unsupported "fpToBits"+  fpFromBits _ _ _ _        = unsupported "fpFromBits"+  fpToRational _ _          = unsupported "fpToRational"+  fpFromRational _ _ _ _ _  = unsupported "fpFromRational"+  unsupported :: String -> SEval SBV a unsupported x = liftIO (X.throw (UnsupportedSymbolicOp x))
src/Cryptol/Backend/What4.hs view
@@ -32,18 +32,16 @@  import qualified What4.Interface as W4 import qualified What4.SWord as SW--import qualified Cryptol.Backend.What4.SFloat as FP+import qualified What4.SFloat as FP  import Cryptol.Backend-import Cryptol.Backend.Concrete( BV(..), ppBV ) import Cryptol.Backend.FloatHelpers import Cryptol.Backend.Monad-   ( Eval(..), EvalError(..), Unsupported(..)-   , delayFill, blackhole, evalSpark+   ( Eval(..), EvalError(..), EvalErrorEx(..)+   , Unsupported(..), delayFill, blackhole, evalSpark+   , modifyCallStack, getCallStack    ) import Cryptol.Utils.Panic-import Cryptol.Utils.PP   data What4 sym =@@ -72,7 +70,7 @@  -- | The symbolic value we computed. data W4Result sym a-  = W4Error !EvalError+  = W4Error !EvalErrorEx     -- ^ A malformed value    | W4Result !(W4.Pred sym) !a@@ -186,7 +184,9 @@  -- | A fully undefined symbolic value evalError :: W4.IsSymExprBuilder sym => EvalError -> W4Eval sym a-evalError err = W4Eval (pure (W4Error err))+evalError err = W4Eval $ W4Conn $ \_sym ->+  do stk <- getCallStack+     pure (W4Error (EvalErrorEx stk err))  -------------------------------------------------------------------------------- @@ -220,17 +220,21 @@       Ready _ -> True       _ -> False -  sDelayFill _ m retry =+  sDelayFill _ m retry msg =     total     do sym <- getSym-       doEval (w4Thunk <$> delayFill (w4Eval m sym) (w4Eval retry sym))+       doEval (w4Thunk <$> delayFill (w4Eval m sym) (w4Eval <$> retry <*> pure sym) msg)    sSpark _ m =     total     do sym   <- getSym        doEval (w4Thunk <$> evalSpark (w4Eval m sym)) +  sModifyCallStack _ f (W4Eval (W4Conn m)) =+    W4Eval (W4Conn \sym -> modifyCallStack f (m sym)) +  sGetCallStack _ = total (doEval getCallStack)+   sDeclareHole _ msg =     total     do (hole, fill) <- doEval (blackhole msg)@@ -288,25 +292,10 @@    integerAsLit _ v = W4.asInteger v -  ppBit _ v-    | Just b <- W4.asConstantPred v = text $! if b then "True" else "False"-    | otherwise                     = text "?"--  ppWord _ opts v-    | Just x <- SW.bvAsUnsignedInteger v-    = ppBV opts (BV (SW.bvWidth v) x)--    | otherwise = text "[?]"--  ppInteger _ _opts v-    | Just x <- W4.asInteger v = integer x-    | otherwise = text "[?]"--  ppFloat _ _opts _ = text "[?]"-   iteBit sym c x y = liftIO (W4.itePred (w4 sym) c x y)   iteWord sym c x y = liftIO (SW.bvIte (w4 sym) c x y)   iteInteger sym c x y = liftIO (W4.intIte (w4 sym) c x y)+  iteFloat sym p x y = liftIO (FP.fpIte (w4 sym) p x y)    bitEq  sym x y = liftIO (W4.eqPred (w4 sym) x y)   bitAnd sym x y = liftIO (W4.andPred (w4 sym) x y)@@ -443,10 +432,18 @@   --------------------------------------------------------------    fpLit sym e p r = liftIO $ FP.fpFromRationalLit (w4 sym) e p r+  fpAsLit _ f = BF e p <$> FP.fpAsLit f+    where (e,p) = FP.fpSize f    fpExactLit sym BF{ bfExpWidth = e, bfPrecWidth = p, bfValue = bf } =     liftIO (FP.fpFromBinary (w4 sym) e p =<< SW.bvLit (w4 sym) (e+p) (floatToBits e p bf)) +  fpNaN sym e p = liftIO (FP.fpNaN (w4 sym) e p)+  fpPosInf sym e p = liftIO (FP.fpPosInf (w4 sym) e p)++  fpToBits sym f = liftIO (FP.fpToBinary (w4 sym) f)+  fpFromBits sym e p w = liftIO (FP.fpFromBinary (w4 sym) e p w)+   fpEq          sym x y = liftIO $ FP.fpEqIEEE (w4 sym) x y   fpLessThan    sym x y = liftIO $ FP.fpLtIEEE (w4 sym) x y   fpGreaterThan sym x y = liftIO $ FP.fpGtIEEE (w4 sym) x y@@ -458,12 +455,30 @@   fpDiv   = fpBinArith FP.fpDiv    fpNeg sym x = liftIO $ FP.fpNeg (w4 sym) x+  fpAbs sym x = liftIO $ FP.fpAbs (w4 sym) x+  fpSqrt sym r x =+    do rm <- fpRoundingMode sym r+       liftIO $ FP.fpSqrt (w4 sym) rm x +  fpFMA sym r x y z =+    do rm <- fpRoundingMode sym r+       liftIO $ FP.fpFMA (w4 sym) rm x y z++  fpIsZero sym x = liftIO $ FP.fpIsZero (w4 sym) x+  fpIsNeg sym x = liftIO $ FP.fpIsNeg (w4 sym) x+  fpIsNaN sym x = liftIO $ FP.fpIsNaN (w4 sym) x+  fpIsInf sym x = liftIO $ FP.fpIsInf (w4 sym) x+  fpIsNorm sym x = liftIO $ FP.fpIsNorm (w4 sym) x+  fpIsSubnorm sym x = liftIO $ FP.fpIsSubnorm (w4 sym) x+   fpFromInteger sym e p r x =     do rm <- fpRoundingMode sym r        liftIO $ FP.fpFromInteger (w4 sym) e p rm x    fpToInteger = fpCvtToInteger++  fpFromRational = fpCvtFromRational+  fpToRational = fpCvtToRational  sModAdd :: W4.IsSymExprBuilder sym =>   sym -> Integer -> W4.SymInteger sym -> W4.SymInteger sym -> IO (W4.SymInteger sym)
− src/Cryptol/Backend/What4/SFloat.hs
@@ -1,362 +0,0 @@-{-# Language DataKinds #-}-{-# Language FlexibleContexts #-}-{-# Language GADTs #-}-{-# Language RankNTypes #-}-{-# Language TypeApplications #-}-{-# Language TypeOperators #-}--- | Working with floats of dynamic sizes.--- This should probably be moved to What4 one day.-module Cryptol.Backend.What4.SFloat-  ( -- * Interface-    SFloat(..)-  , fpReprOf-  , fpSize-  , fpRepr--    -- * Constants-  , fpFresh-  , fpNaN-  , fpPosInf-  , fpFromRationalLit--    -- * Interchange formats-  , fpFromBinary-  , fpToBinary--    -- * Relations-  , SFloatRel-  , fpEq-  , fpEqIEEE-  , fpLtIEEE-  , fpGtIEEE--    -- * Arithmetic-  , SFloatBinArith-  , fpNeg-  , fpAdd-  , fpSub-  , fpMul-  , fpDiv--    -- * Conversions-  , fpRound-  , fpToReal-  , fpFromReal-  , fpFromRational-  , fpToRational-  , fpFromInteger--    -- * Queries-  , fpIsInf, fpIsNaN--  -- * Exceptions-  , UnsupportedFloat(..)-  , FPTypeError(..)-  ) where--import Control.Exception--import Data.Parameterized.Some-import Data.Parameterized.NatRepr--import What4.BaseTypes-import What4.Panic(panic)-import What4.SWord-import What4.Interface---- | Symbolic floating point numbers.-data SFloat sym where-  SFloat :: IsExpr (SymExpr sym) => SymFloat sym fpp -> SFloat sym---------------------------------------------------------------------------------------- | This exception is thrown if the operations try to create a--- floating point value we do not support-data UnsupportedFloat =-  UnsupportedFloat { fpWho :: String, exponentBits, precisionBits :: Integer }-  deriving Show----- | Throw 'UnsupportedFloat' exception-unsupported ::-  String  {- ^ Label -} ->-  Integer {- ^ Exponent width -} ->-  Integer {- ^ Precision width -} ->-  IO a-unsupported l e p =-  throwIO UnsupportedFloat { fpWho         = l-                           , exponentBits  = e-                           , precisionBits = p }--instance Exception UnsupportedFloat---- | This exceptoin is throws if the types don't match.-data FPTypeError =-  FPTypeError { fpExpected :: Some BaseTypeRepr-              , fpActual   :: Some BaseTypeRepr-              }-    deriving Show--instance Exception FPTypeError--fpTypeMismatch :: BaseTypeRepr t1 -> BaseTypeRepr t2 -> IO a-fpTypeMismatch expect actual =-  throwIO FPTypeError { fpExpected = Some expect-                      , fpActual   = Some actual-                      }-fpTypeError :: FloatPrecisionRepr t1 -> FloatPrecisionRepr t2 -> IO a-fpTypeError t1 t2 =-  fpTypeMismatch (BaseFloatRepr t1) (BaseFloatRepr t2)-------------------------------------------------------------------------------------- | Construct the 'FloatPrecisionRepr' with the given parameters.-fpRepr ::-  Integer {- ^ Exponent width -} ->-  Integer {- ^ Precision width -} ->-  Maybe (Some FloatPrecisionRepr)-fpRepr iE iP =-  do Some e    <- someNat iE-     LeqProof  <- testLeq (knownNat @2) e-     Some p    <- someNat iP-     LeqProof  <- testLeq (knownNat @2) p-     pure (Some (FloatingPointPrecisionRepr e p))--fpReprOf ::-  IsExpr (SymExpr sym) => sym -> SymFloat sym fpp -> FloatPrecisionRepr fpp-fpReprOf _ e =-  case exprType e of-    BaseFloatRepr r -> r--fpSize :: SFloat sym -> (Integer,Integer)-fpSize (SFloat f) =-  case exprType f of-    BaseFloatRepr (FloatingPointPrecisionRepr e p) -> (intValue e, intValue p)-------------------------------------------------------------------------------------- Constants---- | A fresh variable of the given type.-fpFresh ::-  IsSymExprBuilder sym =>-  sym ->-  Integer ->-  Integer ->-  IO (SFloat sym)-fpFresh sym e p-  | Just (Some fpp) <- fpRepr e p =-    SFloat <$> freshConstant sym emptySymbol (BaseFloatRepr fpp)-  | otherwise = unsupported "fpFresh" e p---- | Not a number-fpNaN ::-  IsExprBuilder sym =>-  sym ->-  Integer {- ^ Exponent width -} ->-  Integer {- ^ Precision width -} ->-  IO (SFloat sym)-fpNaN sym e p-  | Just (Some fpp) <- fpRepr e p = SFloat <$> floatNaN sym fpp-  | otherwise = unsupported "fpNaN" e p----- | Positive infinity-fpPosInf ::-  IsExprBuilder sym =>-  sym ->-  Integer {- ^ Exponent width -} ->-  Integer {- ^ Precision width -} ->-  IO (SFloat sym)-fpPosInf sym e p-  | Just (Some fpp) <- fpRepr e p = SFloat <$> floatPInf sym fpp-  | otherwise = unsupported "fpPosInf" e p---- | A floating point number corresponding to the given rations.-fpFromRationalLit ::-  IsExprBuilder sym =>-  sym ->-  Integer {- ^ Exponent width -} ->-  Integer {- ^ Precision width -} ->-  Rational ->-  IO (SFloat sym)-fpFromRationalLit sym e p r-  | Just (Some fpp) <- fpRepr e p = SFloat <$> floatLit sym fpp r-  | otherwise = unsupported "fpFromRational" e p----- | Make a floating point number with the given bit representation.-fpFromBinary ::-  IsExprBuilder sym =>-  sym ->-  Integer {- ^ Exponent width -} ->-  Integer {- ^ Precision width -} ->-  SWord sym ->-  IO (SFloat sym)-fpFromBinary sym e p swe-  | DBV sw <- swe-  , Just (Some fpp) <- fpRepr e p-  , FloatingPointPrecisionRepr ew pw <- fpp-  , let expectW = addNat ew pw-  , actual@(BaseBVRepr actualW)  <- exprType sw =-    case testEquality expectW actualW of-      Just Refl -> SFloat <$> floatFromBinary sym fpp sw-      Nothing -- we want to report type correct type errors! :-)-        | Just LeqProof <- testLeq (knownNat @1) expectW ->-                fpTypeMismatch (BaseBVRepr expectW) actual-        | otherwise -> panic "fpFromBits" [ "1 >= 2" ]-  | otherwise = unsupported "fpFromBits" e p--fpToBinary :: IsExprBuilder sym => sym -> SFloat sym -> IO (SWord sym)-fpToBinary sym (SFloat f)-  | FloatingPointPrecisionRepr e p <- fpReprOf sym f-  , Just LeqProof <- testLeq (knownNat @1) (addNat e p)-    = DBV <$> floatToBinary sym f-  | otherwise = panic "fpToBinary" [ "we messed up the types" ]-------------------------------------------------------------------------------------- Arithmetic--fpNeg :: IsExprBuilder sym => sym -> SFloat sym -> IO (SFloat sym)-fpNeg sym (SFloat fl) = SFloat <$> floatNeg sym fl--fpBinArith ::-  IsExprBuilder sym =>-  (forall t.-      sym ->-      RoundingMode ->-      SymFloat sym t ->-      SymFloat sym t ->-      IO (SymFloat sym t)-  ) ->-  sym -> RoundingMode -> SFloat sym -> SFloat sym -> IO (SFloat sym)-fpBinArith fun sym r (SFloat x) (SFloat y) =-  let t1 = sym `fpReprOf` x-      t2 = sym `fpReprOf` y-  in-  case testEquality t1 t2 of-    Just Refl -> SFloat <$> fun sym r x y-    _         -> fpTypeError t1 t2--type SFloatBinArith sym =-  sym -> RoundingMode -> SFloat sym -> SFloat sym -> IO (SFloat sym)--fpAdd :: IsExprBuilder sym => SFloatBinArith sym-fpAdd = fpBinArith floatAdd--fpSub :: IsExprBuilder sym => SFloatBinArith sym-fpSub = fpBinArith floatSub--fpMul :: IsExprBuilder sym => SFloatBinArith sym-fpMul = fpBinArith floatMul--fpDiv :: IsExprBuilder sym => SFloatBinArith sym-fpDiv = fpBinArith floatDiv---------------------------------------------------------------------------------------fpRel ::-  IsExprBuilder sym =>-  (forall t.-    sym ->-    SymFloat sym t ->-    SymFloat sym t ->-    IO (Pred sym)-  ) ->-  sym -> SFloat sym -> SFloat sym -> IO (Pred sym)-fpRel fun sym (SFloat x) (SFloat y) =-  let t1 = sym `fpReprOf` x-      t2 = sym `fpReprOf` y-  in-  case testEquality t1 t2 of-    Just Refl -> fun sym x y-    _         -> fpTypeError t1 t2-----type SFloatRel sym =-  sym -> SFloat sym -> SFloat sym -> IO (Pred sym)--fpEq :: IsExprBuilder sym => SFloatRel sym-fpEq = fpRel floatEq--fpEqIEEE :: IsExprBuilder sym => SFloatRel sym-fpEqIEEE = fpRel floatFpEq--fpLtIEEE :: IsExprBuilder sym => SFloatRel sym-fpLtIEEE = fpRel floatLt--fpGtIEEE :: IsExprBuilder sym => SFloatRel sym-fpGtIEEE = fpRel floatGt------------------------------------------------------------------------------------fpRound ::-  IsExprBuilder sym => sym -> RoundingMode -> SFloat sym -> IO (SFloat sym)-fpRound sym r (SFloat x) = SFloat <$> floatRound sym r x---- | This is undefined on "special" values (NaN,infinity)-fpToReal :: IsExprBuilder sym => sym -> SFloat sym -> IO (SymReal sym)-fpToReal sym (SFloat x) = floatToReal sym x--fpFromReal ::-  IsExprBuilder sym =>-  sym -> Integer -> Integer -> RoundingMode -> SymReal sym -> IO (SFloat sym)-fpFromReal sym e p r x-  | Just (Some repr) <- fpRepr e p = SFloat <$> realToFloat sym repr r x-  | otherwise = unsupported "fpFromReal" e p---fpFromInteger ::-  IsExprBuilder sym =>-  sym -> Integer -> Integer -> RoundingMode -> SymInteger sym -> IO (SFloat sym)-fpFromInteger sym e p r x = fpFromReal sym e p r =<< integerToReal sym x---fpFromRational ::-  IsExprBuilder sym =>-  sym -> Integer -> Integer -> RoundingMode ->-  SymInteger sym -> SymInteger sym -> IO (SFloat sym)-fpFromRational sym e p r x y =-  do num <- integerToReal sym x-     den <- integerToReal sym y-     res <- realDiv sym num den-     fpFromReal sym e p r res--{- | Returns a predicate and two integers, @x@ and @y@.-If the the predicate holds, then @x / y@ is a rational representing-the floating point number. Assumes the FP number is not one of the-special ones that has no real representation. -}-fpToRational ::-  IsSymExprBuilder sym =>-  sym ->-  SFloat sym ->-  IO (Pred sym, SymInteger sym, SymInteger sym)-fpToRational sym fp =-  do r    <- fpToReal sym fp-     x    <- freshConstant sym emptySymbol BaseIntegerRepr-     y    <- freshConstant sym emptySymbol BaseIntegerRepr-     num  <- integerToReal sym x-     den  <- integerToReal sym y-     res  <- realDiv sym num den-     same <- realEq sym r res-     pure (same, x, y)-------------------------------------------------------------------------------------fpIsInf :: IsExprBuilder sym => sym -> SFloat sym -> IO (Pred sym)-fpIsInf sym (SFloat x) = floatIsInf sym x--fpIsNaN :: IsExprBuilder sym => sym -> SFloat sym -> IO (Pred sym)-fpIsNaN sym (SFloat x) = floatIsNaN sym x---
src/Cryptol/Eval.hs view
@@ -27,10 +27,13 @@   , emptyEnv   , evalExpr   , evalDecls+  , evalNewtypeDecls   , evalSel   , evalSetSel   , EvalError(..)+  , EvalErrorEx(..)   , Unsupported(..)+  , WordTooWide(..)   , forceValue   ) where @@ -39,9 +42,11 @@ import Cryptol.Backend.Monad import Cryptol.Eval.Generic ( iteValue ) import Cryptol.Eval.Env+import Cryptol.Eval.Prims import Cryptol.Eval.Type import Cryptol.Eval.Value import Cryptol.ModuleSystem.Name+import Cryptol.Parser.Position import Cryptol.Parser.Selector(ppSelector) import Cryptol.TypeCheck.AST import Cryptol.TypeCheck.Solver.InfNat(Nat'(..))@@ -63,9 +68,10 @@ type EvalEnv = GenEvalEnv Concrete  type EvalPrims sym =-  ( Backend sym, ?evalPrim :: PrimIdent -> Maybe (Either Expr (GenValue sym)) )+  ( Backend sym, ?callStacks :: Bool, ?evalPrim :: PrimIdent -> Maybe (Either Expr (Prim sym)) ) -type ConcPrims = ?evalPrim :: PrimIdent -> Maybe (Either Expr (GenValue Concrete))+type ConcPrims =+  (?callStacks :: Bool, ?evalPrim :: PrimIdent -> Maybe (Either Expr (Prim Concrete)))  -- Expression Evaluation ------------------------------------------------------- @@ -85,10 +91,10 @@   Module         {- ^ Module containing declarations to evaluate -} ->   GenEvalEnv sym {- ^ Environment to extend -} ->   SEval sym (GenEvalEnv sym)-moduleEnv sym m env = evalDecls sym (mDecls m) =<< evalNewtypes sym (mNewtypes m) env+moduleEnv sym m env = evalDecls sym (mDecls m) =<< evalNewtypeDecls sym (mNewtypes m) env  {-# SPECIALIZE evalExpr ::-  ConcPrims =>+  (?range :: Range, ConcPrims) =>   Concrete ->   GenEvalEnv Concrete ->   Expr ->@@ -99,13 +105,17 @@ --   by the `EvalPrims` class, which defines the behavior of bits and words, in --   addition to providing implementations for all the primitives. evalExpr ::-  EvalPrims sym =>+  (?range :: Range, EvalPrims sym) =>   sym ->   GenEvalEnv sym  {- ^ Evaluation environment -} ->   Expr          {- ^ Expression to evaluate -} ->   SEval sym (GenValue sym) evalExpr sym env expr = case expr of +  ELocated r e ->+    let ?range = r in+    evalExpr sym env e+   -- Try to detect when the user has directly written a finite sequence of   -- literal bit values and pack these into a word.   EList es ty@@ -115,22 +125,22 @@         return $ VWord len $           case tryFromBits sym vs of             Just w  -> WordVal <$> w-            Nothing -> do xs <- mapM (sDelay sym Nothing) vs-                          return $ LargeBitsVal len $ finiteSeqMap sym xs+            Nothing -> do xs <- mapM (sDelay sym) vs+                          return $ LargeBitsVal len $ finiteSeqMap xs     | otherwise -> {-# SCC "evalExpr->EList" #-} do-        xs <- mapM (sDelay sym Nothing) vs-        return $ VSeq len $ finiteSeqMap sym xs+        xs <- mapM (sDelay sym) vs+        return $ VSeq len $ finiteSeqMap xs    where     tyv = evalValType (envTypes env) ty     vs  = map eval es     len = genericLength es    ETuple es -> {-# SCC "evalExpr->ETuple" #-} do-     xs <- mapM (sDelay sym Nothing . eval) es+     xs <- mapM (sDelay sym . eval) es      return $ VTuple xs    ERec fields -> {-# SCC "evalExpr->ERec" #-} do-     xs <- traverse (sDelay sym Nothing . eval) fields+     xs <- traverse (sDelay sym . eval) fields      return $ VRecord xs    ESel e sel -> {-# SCC "evalExpr->ESel" #-} do@@ -153,7 +163,15 @@    EVar n -> {-# SCC "evalExpr->EVar" #-} do     case lookupVar n env of-      Just val -> val+      Just (Left p)+        | ?callStacks -> sPushFrame sym n ?range (cacheCallStack sym =<< evalPrim sym n p)+        | otherwise   -> evalPrim sym n p+      Just (Right val)+        | ?callStacks ->+            case nameInfo n of+              Declared{} -> sPushFrame sym n ?range (cacheCallStack sym =<< val)+              Parameter  -> cacheCallStack sym =<< val+        | otherwise -> val       Nothing  -> do         envdoc <- ppEnv sym defaultPPOpts env         panic "[Eval] evalExpr"@@ -163,14 +181,14 @@    ETAbs tv b -> {-# SCC "evalExpr->ETAbs" #-}     case tpKind tv of-      KType -> return $ VPoly    $ \ty -> evalExpr sym (bindType (tpVar tv) (Right ty) env) b-      KNum  -> return $ VNumPoly $ \n  -> evalExpr sym (bindType (tpVar tv) (Left n) env) b+      KType -> tlam sym $ \ty -> evalExpr sym (bindType (tpVar tv) (Right ty) env) b+      KNum  -> nlam sym $ \n  -> evalExpr sym (bindType (tpVar tv) (Left n) env) b       k     -> panic "[Eval] evalExpr" ["invalid kind on type abstraction", show k]    ETApp e ty -> {-# SCC "evalExpr->ETApp" #-} do     eval e >>= \case-      VPoly f     -> f $! (evalValType (envTypes env) ty)-      VNumPoly f  -> f $! (evalNumType (envTypes env) ty)+      f@VPoly{}    -> fromVPoly sym f    $! (evalValType (envTypes env) ty)+      f@VNumPoly{} -> fromVNumPoly sym f $! (evalNumType (envTypes env) ty)       val     -> do vdoc <- ppV val                     panic "[Eval] evalExpr"                       ["expected a polymorphic value"@@ -179,13 +197,13 @@    EApp f v -> {-# SCC "evalExpr->EApp" #-} do     eval f >>= \case-      VFun f' -> f' (eval v)-      it      -> do itdoc <- ppV it-                    panic "[Eval] evalExpr" ["not a function", show itdoc ]+      f'@VFun {} -> fromVFun sym f' (eval v)+      it         -> do itdoc <- ppV it+                       panic "[Eval] evalExpr" ["not a function", show itdoc ]    EAbs n _ty b -> {-# SCC "evalExpr->EAbs" #-}-    return $ VFun (\v -> do env' <- bindVar sym n v env-                            evalExpr sym env' b)+    lam sym (\v -> do env' <- bindVar sym n v env+                      evalExpr sym env' b)    -- XXX these will likely change once there is an evidence value   EProofAbs _ e -> eval e@@ -202,9 +220,31 @@   ppV = ppValue sym defaultPPOpts  +-- | Capure the current call stack from the evaluation monad and+--   annotate function values.  When arguments are later applied+--   to the function, the call stacks will be combined together.+cacheCallStack ::+  Backend sym =>+  sym ->+  GenValue sym ->+  SEval sym (GenValue sym)+cacheCallStack sym v = case v of+  VFun fnstk f ->+    do stk <- sGetCallStack sym+       pure (VFun (combineCallStacks stk fnstk) f)+  VPoly fnstk f ->+    do stk <- sGetCallStack sym+       pure (VPoly (combineCallStacks stk fnstk) f)+  VNumPoly fnstk f ->+    do stk <- sGetCallStack sym+       pure (VNumPoly (combineCallStacks stk fnstk) f)++  -- non-function types don't get annotated+  _ -> pure v+ -- Newtypes -------------------------------------------------------------------- -{-# SPECIALIZE evalNewtypes ::+{-# SPECIALIZE evalNewtypeDecls ::   ConcPrims =>   Concrete ->   Map.Map Name Newtype ->@@ -212,28 +252,34 @@   SEval Concrete (GenEvalEnv Concrete)   #-} -evalNewtypes ::+evalNewtypeDecls ::   EvalPrims sym =>   sym ->   Map.Map Name Newtype ->   GenEvalEnv sym ->   SEval sym (GenEvalEnv sym)-evalNewtypes sym nts env = foldM (flip (evalNewtype sym)) env $ Map.elems nts+evalNewtypeDecls sym nts env = foldM (flip (evalNewtypeDecl sym)) env $ Map.elems nts  -- | Introduce the constructor function for a newtype.-evalNewtype ::+evalNewtypeDecl ::   EvalPrims sym =>   sym ->   Newtype ->   GenEvalEnv sym ->   SEval sym (GenEvalEnv sym)-evalNewtype sym nt = bindVar sym (ntName nt) (return (foldr tabs con (ntParams nt)))+evalNewtypeDecl _sym nt = pure . bindVarDirect (ntName nt) (foldr tabs con (ntParams nt))   where-  tabs _tp body = tlam (\ _ -> body)-  con           = VFun id-{-# INLINE evalNewtype #-}+  con           = PFun PPrim +  tabs tp body =+    case tpKind tp of+      KType -> PTyPoly  (\ _ -> body)+      KNum  -> PNumPoly (\ _ -> body)+      k -> evalPanic "evalNewtypeDecl" ["illegal newtype parameter kind", show (pp k)] +{-# INLINE evalNewtypeDecl #-}++ -- Declarations ----------------------------------------------------------------  {-# SPECIALIZE evalDecls ::@@ -274,7 +320,7 @@       -- declare a "hole" for each declaration       -- and extend the evaluation environment       holes <- mapM (declHole sym) ds-      let holeEnv = IntMap.fromList $ [ (nameUnique nm, h) | (nm,_,h,_) <- holes ]+      let holeEnv = IntMap.fromList $ [ (nameUnique nm, Right h) | (nm,_,h,_) <- holes ]       let env' = env `mappend` emptyEnv{ envVars = holeEnv }        -- evaluate the declaration bodies, building a new evaluation environment@@ -318,12 +364,16 @@   SEval sym () fillHole sym env (nm, sch, _, fill) = do   case lookupVar nm env of-    Nothing -> evalPanic "fillHole" ["Recursive definition not completed", show (ppLocName nm)]-    Just v-     | isValueType env sch -> fill =<< sDelayFill sym v (etaDelay sym (show (ppLocName nm)) env sch v)-     | otherwise           -> fill (etaDelay sym (show (ppLocName nm)) env sch v)+    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) +    _ -> 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@@ -337,6 +387,7 @@   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@@ -357,14 +408,13 @@   SEval sym (GenValue sym) ->   SEval sym (WordValue sym) etaWord sym n val = do-  w <- sDelay sym Nothing (fromWordVal "during eta-expansion" =<< val)-  xs <- memoMap $ IndexSeqMap $ \i ->+  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 ->-  String ->   GenEvalEnv Concrete ->   Schema ->   SEval Concrete (GenValue Concrete) ->@@ -380,23 +430,24 @@ etaDelay ::   Backend sym =>   sym ->-  String ->   GenEvalEnv sym ->   Schema ->   SEval sym (GenValue sym) ->   SEval sym (GenValue sym)-etaDelay sym msg env0 Forall{ sVars = vs0, sType = tp0 } = goTpVars env0 vs0+etaDelay sym env0 Forall{ sVars = vs0, sType = tp0 } = goTpVars env0 vs0   where-  goTpVars env []     val = go (evalValType (envTypes env) tp0) val+  goTpVars env []     val =+     do stk <- sGetCallStack sym+        go stk (evalValType (envTypes env) tp0) val   goTpVars env (v:vs) val =     case tpKind v of-      KType -> return $ VPoly $ \t ->-                  goTpVars (bindType (tpVar v) (Right t) env) vs ( ($t) . fromVPoly =<< val )-      KNum  -> return $ VNumPoly $ \n ->-                  goTpVars (bindType (tpVar v) (Left n) env) vs ( ($n) . fromVNumPoly =<< val )+      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 tp x | isReady sym x = x >>= \case+  go stk tp x | isReady sym x = x >>= \case       VBit{}      -> x       VInteger{}  -> x       VWord{}     -> x@@ -404,33 +455,39 @@       VFloat{}    -> x       VSeq n xs ->         case tp of-          TVSeq _nt el -> return $ VSeq n $ IndexSeqMap $ \i -> go el (lookupSeqMap xs i)+          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 el (lookupSeqMap xs i)+          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 ts xs)+          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 t v) fs 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] -      VFun f ->+      f@VFun{} ->         case tp of-          TVFun _t1 t2 -> return $ VFun $ \a -> go t2 (f a)+          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{} ->@@ -439,7 +496,7 @@       VNumPoly{} ->         evalPanic "type mismatch during eta-expansion" ["Encountered numeric polymorphic value"] -  go tp v =+  go stk tp v = sWithCallStack sym stk $     case tp of       TVBit -> v       TVInteger -> v@@ -449,40 +506,41 @@       TVArray{} -> v        TVSeq n TVBit ->-          do w <- sDelayFill sym (fromWordVal "during eta-expansion" =<< v) (etaWord sym n v)+          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 (Just msg) (fromSeq "during eta-expansion" =<< v)+          do x' <- sDelay sym (fromSeq "during eta-expansion" =<< v)              return $ VSeq n $ IndexSeqMap $ \i -> do-               go el (flip lookupSeqMap i =<< x')+               go stk el (flip lookupSeqMap i =<< x')        TVStream el ->-          do x' <- sDelay sym (Just msg) (fromSeq "during eta-expansion" =<< v)+          do x' <- sDelay sym (fromSeq "during eta-expansion" =<< v)              return $ VStream $ IndexSeqMap $ \i ->-               go el (flip lookupSeqMap i =<< x')+               go stk el (flip lookupSeqMap i =<< x')        TVFun _t1 t2 ->-          do v' <- sDelay sym (Just msg) (fromVFun <$> v)-             return $ VFun $ \a -> go t2 ( ($a) =<< v' )+          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 (Just msg) (fromVTuple <$> v)+             v' <- sDelay sym (fromVTuple <$> v)              return $ VTuple $-                [ go t =<< (flip genericIndex i <$> v')+                [ go stk t =<< (flip genericIndex i <$> v')                 | i <- [0..(n-1)]                 | t <- ts                 ]        TVRec fs ->-          do v' <- sDelay sym (Just msg) (fromVRecord <$> v)+          do v' <- sDelay sym (fromVRecord <$> v)              let err f = evalPanic "expected record value with field" [show f]-             let eta f t = go t =<< (fromMaybe (err f) . lookupField f <$> v')+             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 ->@@ -504,7 +562,7 @@   where   nm = dName d   sch = dSignature d-  msg = unwords ["<<loop>> while evaluating", show (pp nm)]+  msg = unwords ["while evaluating", show (pp nm)]   -- | Evaluate a declaration, extending the evaluation environment.@@ -522,10 +580,11 @@   Decl            {- ^ The declaration to evaluate -} ->   SEval sym (GenEvalEnv sym) evalDecl sym renv env d =+  let ?range = nameLoc (dName d) in   case dDefinition d of     DPrim ->       case ?evalPrim =<< asPrim (dName d) of-        Just (Right v) -> pure (bindVarDirect (dName d) v env)+        Just (Right p) -> pure $ bindVarDirect (dName d) p env         Just (Left ex) -> bindVar sym (dName d) (evalExpr sym renv ex) env         Nothing        -> bindVar sym (dName d) (cryNoPrimError sym (dName d)) env @@ -535,7 +594,6 @@ -- Selectors -------------------------------------------------------------------  {-# SPECIALIZE evalSel ::-  ConcPrims =>   Concrete ->   GenValue Concrete ->   Selector ->@@ -546,7 +604,7 @@ --   tuple and record selections pointwise down into other value constructs --   (e.g., streams and functions). evalSel ::-  EvalPrims sym =>+  Backend sym =>   sym ->   GenValue sym ->   Selector ->@@ -584,12 +642,11 @@                               [ "Unexpected value in list selection"                               , show vdoc ] {-# SPECIALIZE evalSetSel ::-  ConcPrims =>   Concrete -> TValue ->   GenValue Concrete -> Selector -> SEval Concrete (GenValue Concrete) -> SEval Concrete (GenValue Concrete)   #-} evalSetSel :: forall sym.-  EvalPrims sym =>+  Backend sym =>   sym ->   TValue ->   GenValue sym -> Selector -> SEval sym (GenValue sym) -> SEval sym (GenValue sym)@@ -645,7 +702,7 @@ data ListEnv sym = ListEnv   { leVars   :: !(IntMap.IntMap (Integer -> SEval sym (GenValue sym)))       -- ^ Bindings whose values vary by position-  , leStatic :: !(IntMap.IntMap (SEval sym (GenValue sym)))+  , leStatic :: !(IntMap.IntMap (Either (Prim sym) (SEval sym (GenValue sym))))       -- ^ Bindings whose values are constant   , leTypes  :: !TypeEnv   }@@ -654,14 +711,14 @@   l <> r = ListEnv     { leVars   = IntMap.union (leVars  l)  (leVars  r)     , leStatic = IntMap.union (leStatic l) (leStatic r)-    , leTypes  = IntMap.union (leTypes l)  (leTypes r)+    , leTypes  = leTypes l <> leTypes r     }  instance Monoid (ListEnv sym) where   mempty = ListEnv     { leVars   = IntMap.empty     , leStatic = IntMap.empty-    , leTypes  = IntMap.empty+    , leTypes  = mempty     }    mappend l r = l <> r@@ -680,7 +737,7 @@ --   locations. evalListEnv :: ListEnv sym -> Integer -> GenEvalEnv sym evalListEnv (ListEnv vm st tm) i =-    let v = fmap ($i) vm+    let v = fmap (Right . ($i)) vm      in EvalEnv{ envVars = IntMap.union v st                , envTypes = tm                }@@ -698,7 +755,7 @@ -- List Comprehensions ---------------------------------------------------------  {-# SPECIALIZE evalComp ::-  ConcPrims =>+  (?range :: Range, ConcPrims) =>   Concrete ->   GenEvalEnv Concrete ->   Nat'           ->@@ -709,7 +766,7 @@   #-} -- | Evaluate a comprehension. evalComp ::-  EvalPrims sym =>+  (?range :: Range, EvalPrims sym) =>   sym ->   GenEvalEnv sym {- ^ Starting evaluation environment -} ->   Nat'           {- ^ Length of the comprehension -} ->@@ -719,11 +776,11 @@   SEval sym (GenValue sym) evalComp sym env len elty body ms =        do lenv <- mconcat <$> mapM (branchEnvs sym (toListEnv env)) ms-          mkSeq len elty <$> memoMap (IndexSeqMap $ \i -> do+          mkSeq len elty <$> memoMap sym (IndexSeqMap $ \i -> do               evalExpr sym (evalListEnv lenv i) body)  {-# SPECIALIZE branchEnvs ::-  ConcPrims =>+  (?range :: Range, ConcPrims) =>   Concrete ->   ListEnv Concrete ->   [Match] ->@@ -732,7 +789,7 @@ -- | Turn a list of matches into the final environments for each iteration of -- the branch. branchEnvs ::-  EvalPrims sym =>+  (?range :: Range, EvalPrims sym) =>   sym ->   ListEnv sym ->   [Match] ->@@ -740,7 +797,7 @@ branchEnvs sym env matches = foldM (evalMatch sym) env matches  {-# SPECIALIZE evalMatch ::-  ConcPrims =>+  (?range :: Range, ConcPrims) =>   Concrete ->   ListEnv Concrete ->   Match ->@@ -749,7 +806,7 @@  -- | Turn a match into the list of environments it represents. evalMatch ::-  EvalPrims sym =>+  (?range :: Range, EvalPrims sym) =>   sym ->   ListEnv sym ->   Match ->@@ -762,7 +819,7 @@       -- Select from a sequence of finite length.  This causes us to 'stutter'       -- through our previous choices `nLen` times.       Nat nLen -> do-        vss <- memoMap $ IndexSeqMap $ \i -> evalExpr sym (evalListEnv lenv i) expr+        vss <- memoMap sym $ 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@@ -778,7 +835,7 @@       -- `leVars` elements of the comprehension environment into `leStatic` elements       -- by selecting out the 0th element.       Inf -> do-        let allvars = IntMap.union (fmap ($0) (leVars lenv)) (leStatic lenv)+        let allvars = IntMap.union (fmap (Right . ($0)) (leVars lenv)) (leStatic lenv)         let lenv' = lenv { leVars   = IntMap.empty                          , leStatic = allvars                          }
src/Cryptol/Eval/Concrete.hs view
@@ -25,9 +25,9 @@   , toExpr   ) where -import Control.Monad (join, guard, zipWithM, foldM)+import Control.Monad (guard, zipWithM, foldM, mzero) import Data.Bits (Bits(..))-import Data.Ratio((%),numerator,denominator)+import Data.Ratio(numerator,denominator) import Data.Word(Word32, Word64) import MonadLib( ChoiceT, findOne, lift ) import qualified LibBF as FP@@ -44,6 +44,7 @@ import Cryptol.Backend.Monad  import Cryptol.Eval.Generic hiding (logicShift)+import Cryptol.Eval.Prims import Cryptol.Eval.Type import Cryptol.Eval.Value import qualified Cryptol.SHA as SHA@@ -54,7 +55,6 @@ import Cryptol.Utils.Panic (panic) import Cryptol.Utils.Ident (PrimIdent,prelPrim,floatPrim,suiteBPrim,primeECPrim) import Cryptol.Utils.PP-import Cryptol.Utils.Logger(logPrint) import Cryptol.Utils.RecordMap  type Value = GenValue Concrete@@ -63,57 +63,68 @@  -- | Given an expected type, returns an expression that evaluates to -- this value, if we can determine it.-toExpr :: PrimMap -> AST.Type -> Value -> Eval (Maybe AST.Expr)+toExpr :: PrimMap -> TValue -> Value -> Eval (Maybe AST.Expr) toExpr prims t0 v0 = findOne (go t0 v0)   where    prim n = ePrim prims (prelPrim n)  -  go :: AST.Type -> Value -> ChoiceT Eval Expr+  go :: TValue -> Value -> ChoiceT Eval Expr   go ty val =-    case val of-      VRecord vfs ->-        do tfs <- maybe mismatch pure (tIsRec ty)-           -- NB, vfs first argument to keep their display order+    case (ty,val) of+      (TVRec tfs, VRecord vfs) ->+        do -- NB, vfs first argument to keep their display order            res <- zipRecordsM (\_lbl v t -> go t =<< lift v) vfs tfs            case res of              Left _ -> mismatch -- different fields              Right efs -> pure (ERec efs)-      VTuple tvs ->-        do ts <- maybe mismatch pure (tIsTuple ty)-           guard (length ts == length tvs)++      (TVNewtype nt ts tfs, VRecord vfs) ->+        do -- NB, vfs first argument to keep their display order+           res <- zipRecordsM (\_lbl v t -> go t =<< lift v) vfs tfs+           case res of+             Left _ -> mismatch -- different fields+             Right efs ->+               let f = foldl (\x t -> ETApp x (tNumValTy t)) (EVar (ntName nt)) ts+                in pure (EApp f (ERec efs))++      (TVTuple ts, VTuple tvs) ->+        do guard (length ts == length tvs)            ETuple <$> (zipWithM go ts =<< lift (sequence tvs))-      VBit b ->+      (TVBit, VBit b) ->         pure (prim (if b then "True" else "False"))-      VInteger i ->-        -- This works uniformly for values of type Integer or Z n-        pure $ ETApp (ETApp (prim "number") (tNum i)) ty-      VRational (SRational n d) ->+      (TVInteger, VInteger i) ->+        pure $ ETApp (ETApp (prim "number") (tNum i)) tInteger+      (TVIntMod n, VInteger i) ->+        pure $ ETApp (ETApp (prim "number") (tNum i)) (tIntMod (tNum n))++      (TVRational, VRational (SRational n d)) ->         do let n' = ETApp (ETApp (prim "number") (tNum n)) tInteger            let d' = ETApp (ETApp (prim "number") (tNum d)) tInteger            pure $ EApp (EApp (prim "ratio") n') d'-      VFloat i ->-        do (eT, pT) <- maybe mismatch pure (tIsFloat ty)-           pure (floatToExpr prims eT pT (bfValue i))-      VSeq n svs ->-        do (_a, b) <- maybe mismatch pure (tIsSeq ty)-           ses <- traverse (go b) =<< lift (sequence (enumerateSeqMap n svs))-           pure $ EList ses b-      VWord _ wval ->++      (TVFloat e p, VFloat i) ->+           pure (floatToExpr prims (tNum e) (tNum p) (bfValue i))+      (TVSeq _ b, VSeq n svs) ->+        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)-           pure $ ETApp (ETApp (prim "number") (tNum v)) ty-      VStream _  -> fail "cannot construct infinite expressions"-      VFun _     -> fail "cannot convert function values to expressions"-      VPoly _    -> fail "cannot convert polymorphic values to expressions"-      VNumPoly _ -> fail "cannot convert polymorphic values to expressions"+           pure $ ETApp (ETApp (prim "number") (tNum v)) (tWord (tNum n))++      (_,VStream{})  -> mzero+      (_,VFun{})     -> mzero+      (_,VPoly{})    -> mzero+      (_,VNumPoly{}) -> mzero+      _ -> mismatch     where       mismatch :: forall a. ChoiceT Eval a       mismatch =         do doc <- lift (ppValue Concrete defaultPPOpts val)            panic "Cryptol.Eval.Concrete.toExpr"              ["type mismatch:"-             , pretty ty+             , pretty (tValTy ty)              , render doc              ] @@ -139,153 +150,18 @@  -- Primitives ------------------------------------------------------------------ -primTable :: EvalOpts -> Map PrimIdent Value-primTable eOpts = let sym = Concrete in-  Map.union (floatPrims sym) $+primTable :: IO EvalOpts -> Map PrimIdent (Prim Concrete)+primTable getEOpts = let sym = Concrete in+  Map.union (genericPrimTable sym getEOpts) $+  Map.union (genericFloatTable sym) $   Map.union suiteBPrims $   Map.union primeECPrims $    Map.fromList $ map (\(n, v) -> (prelPrim n, v)) -  [ -- Literals-    ("True"       , VBit (bitLit sym True))-  , ("False"      , VBit (bitLit sym False))-  , ("number"     , {-# SCC "Prelude::number" #-}-                    ecNumberV sym)-  , ("ratio"      , {-# SCC "Prelude::ratio" #-}-                    ratioV sym)-  , ("fraction"   , ecFractionV sym)---    -- Zero-  , ("zero"       , {-# SCC "Prelude::zero" #-}-                    VPoly (zeroV sym))--    -- Logic-  , ("&&"         , {-# SCC "Prelude::(&&)" #-}-                    binary (andV sym))-  , ("||"         , {-# SCC "Prelude::(||)" #-}-                    binary (orV sym))-  , ("^"          , {-# SCC "Prelude::(^)" #-}-                    binary (xorV sym))-  , ("complement" , {-# SCC "Prelude::complement" #-}-                    unary  (complementV sym))--    -- Ring-  , ("fromInteger", {-# SCC "Prelude::fromInteger" #-}-                    fromIntegerV sym)-  , ("+"          , {-# SCC "Prelude::(+)" #-}-                    binary (addV sym))-  , ("-"          , {-# SCC "Prelude::(-)" #-}-                    binary (subV sym))-  , ("*"          , {-# SCC "Prelude::(*)" #-}-                    binary (mulV sym))-  , ("negate"     , {-# SCC "Prelude::negate" #-}-                    unary (negateV sym))--    -- Integral-  , ("toInteger"  , {-# SCC "Prelude::toInteger" #-}-                    toIntegerV sym)-  , ("/"          , {-# SCC "Prelude::(/)" #-}-                    binary (divV sym))-  , ("%"          , {-# SCC "Prelude::(%)" #-}-                    binary (modV sym))-  , ("^^"         , {-# SCC "Prelude::(^^)" #-}-                    expV sym)-  , ("infFrom"    , {-# SCC "Prelude::infFrom" #-}-                    infFromV sym)-  , ("infFromThen", {-# SCC "Prelude::infFromThen" #-}-                    infFromThenV sym)--    -- Field-  , ("recip"      , {-# SCC "Prelude::recip" #-}-                    recipV sym)-  , ("/."         , {-# SCC "Prelude::(/.)" #-}-                    fieldDivideV sym)--    -- Round-  , ("floor"      , {-# SCC "Prelude::floor" #-}-                    unary (floorV sym))-  , ("ceiling"    , {-# SCC "Prelude::ceiling" #-}-                    unary (ceilingV sym))-  , ("trunc"      , {-# SCC "Prelude::trunc" #-}-                    unary (truncV sym))-  , ("roundAway"  , {-# SCC "Prelude::roundAway" #-}-                    unary (roundAwayV sym))-  , ("roundToEven", {-# SCC "Prelude::roundToEven" #-}-                    unary (roundToEvenV sym))--    -- Bitvector specific operations-  , ("/$"         , {-# SCC "Prelude::(/$)" #-}-                    sdivV sym)-  , ("%$"         , {-# SCC "Prelude::(%$)" #-}-                    smodV sym)-  , ("lg2"        , {-# SCC "Prelude::lg2" #-}-                    lg2V sym)-  , (">>$"        , {-# SCC "Prelude::(>>$)" #-}+  [ (">>$"        , {-# SCC "Prelude::(>>$)" #-}                     sshrV) -    -- Cmp-  , ("<"          , {-# SCC "Prelude::(<)" #-}-                    binary (lessThanV sym))-  , (">"          , {-# SCC "Prelude::(>)" #-}-                    binary (greaterThanV sym))-  , ("<="         , {-# SCC "Prelude::(<=)" #-}-                    binary (lessThanEqV sym))-  , (">="         , {-# SCC "Prelude::(>=)" #-}-                    binary (greaterThanEqV sym))-  , ("=="         , {-# SCC "Prelude::(==)" #-}-                    binary (eqV sym))-  , ("!="         , {-# SCC "Prelude::(!=)" #-}-                    binary (distinctV sym))--    -- SignedCmp-  , ("<$"         , {-# SCC "Prelude::(<$)" #-}-                    binary (signedLessThanV sym))--    -- Finite enumerations-  , ("fromTo"     , {-# SCC "Prelude::fromTo" #-}-                    fromToV sym)-  , ("fromThenTo" , {-# SCC "Prelude::fromThenTo" #-}-                    fromThenToV sym)--    -- Sequence manipulations-  , ("#"          , {-# SCC "Prelude::(#)" #-}-                    nlam $ \ front ->-                    nlam $ \ back  ->-                    tlam $ \ elty  ->-                    lam  $ \ l     -> return $-                    lam  $ \ r     -> join (ccatV sym front back elty <$> l <*> r))---  , ("join"       , {-# SCC "Prelude::join" #-}-                    nlam $ \ parts ->-                    nlam $ \ (finNat' -> each)  ->-                    tlam $ \ a     ->-                    lam  $ \ x     ->-                      joinV sym parts each a =<< x)--  , ("split"      , {-# SCC "Prelude::split" #-}-                    ecSplitV sym)--  , ("splitAt"    , {-# SCC "Prelude::splitAt" #-}-                    nlam $ \ front ->-                    nlam $ \ back  ->-                    tlam $ \ a     ->-                    lam  $ \ x     ->-                       splitAtV sym front back a =<< x)--  , ("reverse"    , {-# SCC "Prelude::reverse" #-}-                    nlam $ \_a ->-                    tlam $ \_b ->-                     lam $ \xs -> reverseV sym =<< xs)--  , ("transpose"  , {-# SCC "Prelude::transpose" #-}-                    nlam $ \a ->-                    nlam $ \b ->-                    tlam $ \c ->-                     lam $ \xs -> transposeV sym a b c =<< xs)-     -- Shifts and rotates   , ("<<"         , {-# SCC "Prelude::(<<)" #-}                     logicShift shiftLW shiftLS)@@ -308,56 +184,12 @@   , ("updateEnd"  , {-# SCC "Prelude::updateEnd" #-}                     updatePrim sym updateBack_word updateBack) -    -- Misc-  , ("foldl"      , {-# SCC "Prelude::foldl" #-}-                    foldlV sym)--  , ("foldl'"     , {-# SCC "Prelude::foldl'" #-}-                    foldl'V sym)--  , ("deepseq"    , {-# SCC "Prelude::deepseq" #-}-                    tlam $ \_a ->-                    tlam $ \_b ->-                     lam $ \x -> pure $-                     lam $ \y ->-                       do _ <- forceValue =<< x-                          y)--  , ("parmap"     , {-# SCC "Prelude::parmap" #-}-                    parmapV sym)--  , ("fromZ"      , {-# SCC "Prelude::fromZ" #-}-                    fromZV sym)--  , ("error"      , {-# SCC "Prelude::error" #-}-                      tlam $ \a ->-                      nlam $ \_ ->-                       lam $ \s -> errorV sym a =<< (valueToString sym =<< s))--  , ("random"      , {-# SCC "Prelude::random" #-}-                     tlam $ \a ->-                     wlam sym $ \(bvVal -> x) -> randomV sym a x)--  , ("trace"       , {-# SCC "Prelude::trace" #-}-                     nlam $ \_n ->-                     tlam $ \_a ->-                     tlam $ \_b ->-                      lam $ \s -> return $-                      lam $ \x -> return $-                      lam $ \y -> do-                         msg <- valueToString sym =<< s-                         let EvalOpts { evalPPOpts, evalLogger } = eOpts-                         doc <- ppValue sym evalPPOpts =<< x-                         yv <- y-                         io $ logPrint evalLogger-                             $ if null msg then doc else text msg <+> doc-                         return yv)-    , ("pmult",-        ilam $ \u ->-        ilam $ \v ->-          wlam Concrete $ \(BV _ x) -> return $-          wlam Concrete $ \(BV _ y) ->+        PFinPoly \u ->+        PFinPoly \v ->+        PWordFun \(BV _ x) ->+        PWordFun \(BV _ y) ->+        PPrim             let z = if u <= v then                       F2.pmult (fromInteger (u+1)) x y                     else@@ -365,56 +197,62 @@              in return . VWord (1+u+v) . pure . WordVal . mkBv (1+u+v) $! z)     , ("pmod",-        ilam $ \_u ->-        ilam $ \v ->-        wlam Concrete $ \(BV w x) -> return $-        wlam Concrete $ \(BV _ m) ->+        PFinPoly \_u ->+        PFinPoly \v ->+        PWordFun \(BV w x) ->+        PWordFun \(BV _ m) ->+        PPrim           do assertSideCondition sym (m /= 0) DivideByZero              return . VWord v . pure . WordVal . mkBv v $! F2.pmod (fromInteger w) x m)    , ("pdiv",-        ilam $ \_u ->-        ilam $ \_v ->-        wlam Concrete $ \(BV w x) -> return $-        wlam Concrete $ \(BV _ m) ->+        PFinPoly \_u ->+        PFinPoly \_v ->+        PWordFun \(BV w x) ->+        PWordFun \(BV _ m) ->+        PPrim           do assertSideCondition sym (m /= 0) DivideByZero              return . VWord w . pure . WordVal . mkBv w $! F2.pdiv (fromInteger w) x m)   ]  -primeECPrims :: Map.Map PrimIdent Value+primeECPrims :: Map.Map PrimIdent (Prim Concrete) primeECPrims = Map.fromList $ map (\(n,v) -> (primeECPrim n, v))   [ ("ec_double", {-# SCC "PrimeEC::ec_double" #-}-       ilam $ \p ->-        lam $ \s ->+       PFinPoly \p ->+       PFun     \s ->+       PPrim           do s' <- toProjectivePoint =<< s              let r = PrimeEC.ec_double (PrimeEC.primeModulus p) s'              fromProjectivePoint $! r)    , ("ec_add_nonzero", {-# SCC "PrimeEC::ec_add_nonzero" #-}-       ilam $ \p ->-        lam $ \s -> pure $-        lam $ \t ->+       PFinPoly \p ->+       PFun     \s ->+       PFun     \t ->+       PPrim            do s' <- toProjectivePoint =<< s              t' <- toProjectivePoint =<< t              let r = PrimeEC.ec_add_nonzero (PrimeEC.primeModulus p) s' t'              fromProjectivePoint $! r)    , ("ec_mult", {-# SCC "PrimeEC::ec_mult" #-}-       ilam $ \p ->-        lam $ \d -> pure $-        lam $ \s ->+       PFinPoly \p ->+       PFun     \d ->+       PFun     \s ->+       PPrim           do d' <- fromVInteger <$> d              s' <- toProjectivePoint =<< s              let r = PrimeEC.ec_mult (PrimeEC.primeModulus p) d' s'              fromProjectivePoint $! r)    , ("ec_twin_mult", {-# SCC "PrimeEC::ec_twin_mult" #-}-       ilam $ \p ->-        lam $ \d0 -> pure $-        lam $ \s  -> pure $-        lam $ \d1 -> pure $-        lam $ \t  ->+       PFinPoly \p  ->+       PFun     \d0 ->+       PFun     \s  ->+       PFun     \d1 ->+       PFun     \t  ->+       PPrim           do d0' <- fromVInteger <$> d0              s'  <- toProjectivePoint =<< s              d1' <- fromVInteger <$> d1@@ -436,59 +274,64 @@   -suiteBPrims :: Map.Map PrimIdent Value+suiteBPrims :: Map.Map PrimIdent (Prim Concrete) suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))   [ ("processSHA2_224", {-# SCC "SuiteB::processSHA2_224" #-}-                      ilam $ \n ->-                       lam $ \xs ->-                         do blks <- enumerateSeqMap n . fromVSeq <$> xs-                            (SHA.SHA256S w0 w1 w2 w3 w4 w5 w6 _) <--                               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 Concrete (map f [w0,w1,w2,w3,w4,w5,w6])-                            seq zs (pure (VSeq 7 zs)))+     PFinPoly \n ->+     PFun     \xs ->+     PPrim+        do blks <- enumerateSeqMap n . fromVSeq <$> xs+           (SHA.SHA256S w0 w1 w2 w3 w4 w5 w6 _) <-+              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])+           seq zs (pure (VSeq 7 zs)))    , ("processSHA2_256", {-# SCC "SuiteB::processSHA2_256" #-}-                      ilam $ \n ->-                       lam $ \xs ->-                         do blks <- enumerateSeqMap n . fromVSeq <$> xs-                            (SHA.SHA256S w0 w1 w2 w3 w4 w5 w6 w7) <--                              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 Concrete (map f [w0,w1,w2,w3,w4,w5,w6,w7])-                            seq zs (pure (VSeq 8 zs)))+     PFinPoly \n ->+     PFun     \xs ->+     PPrim+        do blks <- enumerateSeqMap n . fromVSeq <$> xs+           (SHA.SHA256S w0 w1 w2 w3 w4 w5 w6 w7) <-+             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])+           seq zs (pure (VSeq 8 zs)))    , ("processSHA2_384", {-# SCC "SuiteB::processSHA2_384" #-}-                      ilam $ \n ->-                       lam $ \xs ->-                         do blks <- enumerateSeqMap n . fromVSeq <$> xs-                            (SHA.SHA512S w0 w1 w2 w3 w4 w5 _ _) <--                              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 Concrete (map f [w0,w1,w2,w3,w4,w5])-                            seq zs (pure (VSeq 6 zs)))+     PFinPoly \n ->+     PFun     \xs ->+     PPrim+        do blks <- enumerateSeqMap n . fromVSeq <$> xs+           (SHA.SHA512S w0 w1 w2 w3 w4 w5 _ _) <-+             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])+           seq zs (pure (VSeq 6 zs)))    , ("processSHA2_512", {-# SCC "SuiteB::processSHA2_512" #-}-                      ilam $ \n ->-                       lam $ \xs ->-                         do blks <- enumerateSeqMap n . fromVSeq <$> xs-                            (SHA.SHA512S w0 w1 w2 w3 w4 w5 w6 w7) <--                              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 Concrete (map f [w0,w1,w2,w3,w4,w5,w6,w7])-                            seq zs (pure (VSeq 8 zs)))+     PFinPoly \n ->+     PFun     \xs ->+     PPrim+        do blks <- enumerateSeqMap n . fromVSeq <$> xs+           (SHA.SHA512S w0 w1 w2 w3 w4 w5 w6 w7) <-+             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])+           seq zs (pure (VSeq 8 zs)))    , ("AESKeyExpand", {-# SCC "SuiteB::AESKeyExpand" #-}-      ilam $ \k ->-       lam $ \seed ->+      PFinPoly \k ->+      PFun     \seed ->+      PPrim          do ss <- fromVSeq <$> seed             let toWord :: Integer -> Eval Word32                 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESInfKeyExpand" =<< lookupSeqMap ss i)@@ -497,10 +340,11 @@             kws <- mapM toWord [0 .. k-1]             let ws = AES.keyExpansionWords k kws             let len = 4*(k+7)-            pure (VSeq len (finiteSeqMap Concrete (map fromWord ws))))+            pure (VSeq len (finiteSeqMap (map fromWord ws))))    , ("AESInvMixColumns", {-# SCC "SuiteB::AESInvMixColumns" #-}-      lam $ \st ->+      PFun \st ->+      PPrim          do ss <- fromVSeq <$> st             let toWord :: Integer -> Eval Word32                 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESInvMixColumns" =<< lookupSeqMap ss i)@@ -508,10 +352,11 @@                 fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger             ws <- mapM toWord [0,1,2,3]             let ws' = AES.invMixColumns ws-            pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')+            pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')    , ("AESEncRound", {-# SCC "SuiteB::AESEncRound" #-}-      lam $ \st ->+      PFun \st ->+      PPrim          do ss <- fromVSeq <$> st             let toWord :: Integer -> Eval Word32                 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESEncRound" =<< lookupSeqMap ss i)@@ -519,10 +364,11 @@                 fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger             ws <- mapM toWord [0,1,2,3]             let ws' = AES.aesRound ws-            pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')+            pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')    , ("AESEncFinalRound", {-# SCC "SuiteB::AESEncFinalRound" #-}-      lam $ \st ->+     PFun \st ->+     PPrim          do ss <- fromVSeq <$> st             let toWord :: Integer -> Eval Word32                 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESEncFinalRound" =<< lookupSeqMap ss i)@@ -530,10 +376,11 @@                 fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger             ws <- mapM toWord [0,1,2,3]             let ws' = AES.aesFinalRound ws-            pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')+            pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')    , ("AESDecRound", {-# SCC "SuiteB::AESDecRound" #-}-      lam $ \st ->+      PFun \st ->+      PPrim          do ss <- fromVSeq <$> st             let toWord :: Integer -> Eval Word32                 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESDecRound" =<< lookupSeqMap ss i)@@ -541,10 +388,11 @@                 fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger             ws <- mapM toWord [0,1,2,3]             let ws' = AES.aesInvRound ws-            pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')+            pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')    , ("AESDecFinalRound", {-# SCC "SuiteB::AESDecFinalRound" #-}-      lam $ \st ->+     PFun \st ->+     PPrim          do ss <- fromVSeq <$> st             let toWord :: Integer -> Eval Word32                 toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESDecFinalRound" =<< lookupSeqMap ss i)@@ -552,7 +400,7 @@                 fromWord = pure . VWord 32 . pure . WordVal . BV 32 . toInteger             ws <- mapM toWord [0,1,2,3]             let ws' = AES.aesInvFinalRound ws-            pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')+            pure . VSeq 4 . finiteSeqMap . map fromWord $ ws')   ]  @@ -603,12 +451,13 @@  -------------------------------------------------------------------------------- -sshrV :: Value+sshrV :: Prim Concrete sshrV =-  nlam $ \_n ->-  tlam $ \ix ->-  wlam Concrete $ \(BV w x) -> return $-  lam $ \y ->+  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@@ -618,14 +467,15 @@               -- ^ The function may assume its arguments are masked.               -- It is responsible for masking its result if needed.            -> (Nat' -> TValue -> SeqMap Concrete -> Integer -> SeqMap Concrete)-           -> Value-logicShift opW opS-  = nlam $ \ a ->-    tlam $ \ _ix ->-    tlam $ \ c ->-     lam  $ \ l -> return $-     lam  $ \ r -> do-        i <- r >>= \case+           -> 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"]@@ -795,55 +645,3 @@ updateBack_word (Nat n) _eltTy bs (Right w) val = do   idx <- bvVal <$> asWordVal Concrete w   updateWordValue Concrete bs (n - idx - 1) (fromVBit <$> val)---floatPrims :: Concrete -> Map PrimIdent Value-floatPrims sym = Map.fromList [ (floatPrim i,v) | (i,v) <- nonInfixTable ]-  where-  (~>) = (,)-  nonInfixTable =-    [ "fpNaN"       ~> ilam \e -> ilam \p ->-                        VFloat BF { bfValue = FP.bfNaN-                                  , bfExpWidth = e, bfPrecWidth = p }--    , "fpPosInf"    ~> ilam \e -> ilam \p ->-                       VFloat BF { bfValue = FP.bfPosInf-                                 , bfExpWidth = e, bfPrecWidth = p }--    , "fpFromBits"  ~> ilam \e -> ilam \p -> wlam sym \bv ->-                       pure $ VFloat $ floatFromBits e p $ bvVal bv--    , "fpToBits"    ~> ilam \e -> ilam \p -> flam \x ->-                       pure $ word sym (e + p)-                            $ floatToBits e p-                            $ bfValue x-    , "=.="         ~> ilam \_ -> ilam \_ -> flam \x -> pure $ flam \y ->-                       pure $ VBit-                            $ bitLit sym-                            $ FP.bfCompare (bfValue x) (bfValue y) == EQ--    , "fpIsFinite"  ~> ilam \_ -> ilam \_ -> flam \x ->-                       pure $ VBit $ bitLit sym $ FP.bfIsFinite $ bfValue x--      -- From Backend class-    , "fpAdd"      ~> fpBinArithV sym fpPlus-    , "fpSub"      ~> fpBinArithV sym fpMinus-    , "fpMul"      ~> fpBinArithV sym fpMult-    , "fpDiv"      ~> fpBinArithV sym fpDiv--    , "fpFromRational" ~>-      ilam \e -> ilam \p -> wlam sym \r -> pure $ lam \x ->-        do rat <- fromVRational <$> x-           VFloat <$> do mode <- fpRoundMode sym r-                         pure $ floatFromRational e p mode-                              $ sNum rat % sDenom rat-    , "fpToRational" ~>-      ilam \_e -> ilam \_p -> flam \fp ->-      case floatToRational "fpToRational" fp of-        Left err -> raiseError sym err-        Right r  -> pure $-                      VRational-                        SRational { sNum = numerator r, sDenom = denominator r }-    ]--
src/Cryptol/Eval/Env.hs view
@@ -16,8 +16,7 @@  import Cryptol.Backend -import Cryptol.Backend.Monad( PPOpts )-+import Cryptol.Eval.Prims import Cryptol.Eval.Type import Cryptol.Eval.Value import Cryptol.ModuleSystem.Name@@ -25,7 +24,6 @@ import Cryptol.TypeCheck.Solver.InfNat import Cryptol.Utils.PP - import qualified Data.IntMap.Strict as IntMap import Data.Semigroup @@ -37,29 +35,31 @@ -- Evaluation Environment ------------------------------------------------------  data GenEvalEnv sym = EvalEnv-  { envVars       :: !(IntMap.IntMap (SEval sym (GenValue sym)))+  { envVars       :: !(IntMap.IntMap (Either (Prim sym) (SEval sym (GenValue sym))))   , envTypes      :: !TypeEnv   } deriving Generic  instance Semigroup (GenEvalEnv sym) where   l <> r = EvalEnv     { envVars     = IntMap.union (envVars l) (envVars r)-    , envTypes    = IntMap.union (envTypes l) (envTypes r)+    , envTypes    = envTypes l <> envTypes r     }  instance Monoid (GenEvalEnv sym) where   mempty = EvalEnv     { envVars       = IntMap.empty-    , envTypes      = IntMap.empty+    , envTypes      = mempty     }-   mappend l r = l <> r  ppEnv :: Backend sym => sym -> PPOpts -> GenEvalEnv sym -> SEval sym Doc ppEnv sym opts env = brackets . fsep <$> mapM bind (IntMap.toList (envVars env))   where-   bind (k,v) = do vdoc <- ppValue sym opts =<< v-                   return (int k <+> text "->" <+> vdoc)+   bind (k,Left _) =+      do return (int k <+> text "<<prim>>")+   bind (k,Right v) =+      do vdoc <- ppValue sym opts =<< v+         return (int k <+> text "->" <+> vdoc)  -- | Evaluation environment with no bindings emptyEnv :: GenEvalEnv sym@@ -75,32 +75,32 @@   SEval sym (GenEvalEnv sym) bindVar sym n val env = do   let nm = show $ ppLocName n-  val' <- sDelay sym (Just nm) val-  return $ env{ envVars = IntMap.insert (nameUnique n) val' (envVars env) }+  val' <- sDelayFill sym val Nothing nm+  return $ env{ envVars = IntMap.insert (nameUnique n) (Right val') (envVars env) }  -- | Bind a variable to a value in the evaluation environment, without --   creating a thunk. bindVarDirect ::   Backend sym =>   Name ->-  GenValue sym ->+  Prim sym ->   GenEvalEnv sym ->   GenEvalEnv sym bindVarDirect n val env = do-  env{ envVars = IntMap.insert (nameUnique n) (pure val) (envVars env) }+  env{ envVars = IntMap.insert (nameUnique n) (Left val) (envVars env) }  -- | Lookup a variable in the environment. {-# INLINE lookupVar #-}-lookupVar :: Name -> GenEvalEnv sym -> Maybe (SEval sym (GenValue sym))+lookupVar :: Name -> GenEvalEnv sym -> Maybe (Either (Prim sym) (SEval sym (GenValue sym))) lookupVar n env = IntMap.lookup (nameUnique n) (envVars env)  -- | Bind a type variable of kind *. {-# INLINE bindType #-} bindType :: TVar -> Either Nat' TValue -> GenEvalEnv sym -> GenEvalEnv sym-bindType p ty env = env { envTypes = IntMap.insert (tvUnique p) ty (envTypes env) }+bindType p ty env = env{ envTypes = bindTypeVar p ty (envTypes env) }  -- | Lookup a type variable. {-# INLINE lookupType #-} lookupType :: TVar -> GenEvalEnv sym -> Maybe (Either Nat' TValue)-lookupType p env = IntMap.lookup (tvUnique p) (envTypes env)+lookupType p env = lookupTypeVar p (envTypes env) 
src/Cryptol/Eval/Generic.hs view
@@ -11,6 +11,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE Rank2Types #-}@@ -27,24 +28,28 @@ import System.Random.TF.Gen (seedTFGen)  import Data.Bits (testBit, (.&.), 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.Backend import Cryptol.Backend.Concrete (Concrete(..))-import Cryptol.Backend.Monad ( Eval, evalPanic, EvalError(..), Unsupported(..) )+import Cryptol.Backend.Monad( Eval, evalPanic, EvalError(..), Unsupported(..) ) import Cryptol.Testing.Random( randomValue ) +import Cryptol.Eval.Prims import Cryptol.Eval.Type import Cryptol.Eval.Value+import Cryptol.Utils.Ident (PrimIdent, prelPrim, floatPrim)+import Cryptol.Utils.Logger(logPrint) import Cryptol.Utils.Panic (panic)+import Cryptol.Utils.PP import Cryptol.Utils.RecordMap  - {-# SPECIALIZE mkLit :: Concrete -> TValue -> Integer -> Eval (GenValue Concrete)   #-} @@ -63,14 +68,15 @@     _                            -> evalPanic "Cryptol.Eval.Prim.evalConst"                                     [ "Invalid type for number" ] -{-# SPECIALIZE ecNumberV :: Concrete -> GenValue Concrete+{-# SPECIALIZE ecNumberV :: Concrete -> Prim Concrete   #-}  -- | Make a numeric constant.-ecNumberV :: Backend sym => sym -> GenValue sym+ecNumberV :: Backend sym => sym -> Prim sym ecNumberV sym =-  nlam $ \valT ->-  VPoly $ \ty ->+  PNumPoly \valT ->+  PTyPoly \ty ->+  PPrim   case valT of     Nat v -> mkLit sym ty v     _ -> evalPanic "Cryptol.Eval.Prim.evalConst"@@ -80,32 +86,38 @@              ]  - {-# SPECIALIZE intV :: Concrete -> Integer -> TValue -> Eval (GenValue Concrete)   #-} intV :: Backend sym => sym -> SInteger sym -> TValue -> SEval sym (GenValue sym)-intV sym i = ringNullary sym (\w -> wordFromInt sym w i) (pure i) (\m -> intToZn sym m i) (intToRational sym i)-            (\e p -> fpRndMode sym >>= \r -> fpFromInteger sym e p r i)+intV sym i =+  ringNullary sym+    (\w -> wordFromInt sym w i)+    (pure i)+    (\m -> intToZn sym m i)+    (intToRational sym i)+    (\e p -> fpRndMode sym >>= \r -> fpFromInteger sym e p r i) -{-# SPECIALIZE ratioV :: Concrete -> GenValue Concrete #-}-ratioV :: Backend sym => sym -> GenValue sym+{-# SPECIALIZE ratioV :: Concrete -> Prim Concrete #-}+ratioV :: Backend sym => sym -> Prim sym ratioV sym =-  lam $ \x -> return $-  lam $ \y ->+  PFun   \x ->+  PFun   \y ->+  PPrim     do x' <- fromVInteger <$> x        y' <- fromVInteger <$> y        VRational <$> ratio sym x' y' -{-# SPECIALIZE ecFractionV :: Concrete -> GenValue Concrete+{-# SPECIALIZE ecFractionV :: Concrete -> Prim Concrete   #-}-ecFractionV :: Backend sym => sym -> GenValue sym+ecFractionV :: Backend sym => sym -> Prim sym ecFractionV sym =-  ilam  \n ->-  ilam  \d ->-  ilam  \_r ->-  VPoly \ty ->+  PFinPoly \n  ->+  PFinPoly \d  ->+  PFinPoly \_r ->+  PTyPoly  \ty ->+  PPrim     case ty of-      TVFloat e p -> VFloat    <$> fpLit sym e p (n % d)+      TVFloat e p -> VFloat <$> fpLit sym e p (n % d)       TVRational ->         do x <- integerLit sym n            y <- integerLit sym d@@ -116,34 +128,38 @@   -{-# SPECIALIZE fromZV :: Concrete -> GenValue Concrete #-}-fromZV :: Backend sym => sym -> GenValue sym+{-# SPECIALIZE fromZV :: Concrete -> Prim Concrete #-}+fromZV :: Backend sym => sym -> Prim sym fromZV sym =-  nlam $ \(finNat' -> n) ->-  lam $ \v -> VInteger <$> (znToInt sym n . fromVInteger =<< v)+  PFinPoly \n ->+  PFun     \v ->+  PPrim+    (VInteger <$> (znToInt sym n . fromVInteger =<< v))  -- Operation Lifting -----------------------------------------------------------   type Binary sym = TValue -> GenValue sym -> GenValue sym -> SEval sym (GenValue sym) -{-# SPECIALIZE binary :: Binary Concrete -> GenValue Concrete+{-# SPECIALIZE binary :: Binary Concrete -> Prim Concrete   #-}-binary :: Backend sym => Binary sym -> GenValue sym-binary f = tlam $ \ ty ->-            lam $ \ a  -> return $-            lam $ \ b  -> do-               --io $ putStrLn "Entering a binary function"-               join (f ty <$> a <*> b)+binary :: Backend sym => Binary sym -> Prim sym+binary f = PTyPoly \ty ->+           PFun    \a  ->+           PFun    \b  ->+           PPrim $+             do x <- a+                y <- b+                f ty x y  type Unary sym = TValue -> GenValue sym -> SEval sym (GenValue sym) -{-# SPECIALIZE unary :: Unary Concrete -> GenValue Concrete+{-# SPECIALIZE unary :: Unary Concrete -> Prim Concrete   #-}-unary :: Backend sym => Unary sym -> GenValue sym-unary f = tlam $ \ ty ->-           lam $ \ a  -> f ty =<< a-+unary :: Backend sym => Unary sym -> Prim sym+unary f = PTyPoly \ty ->+          PFun    \a  ->+          PPrim (f ty =<< a)  type BinWord sym = Integer -> SWord sym -> SWord sym -> SEval sym (SWord sym) @@ -200,37 +216,41 @@       | isTBit a -> do                   lw <- fromVWord sym "ringLeft" l                   rw <- fromVWord sym "ringRight" r-                  return $ VWord w (WordVal <$> opw w lw rw)-      | otherwise -> VSeq w <$> (join (zipSeqMap (loop a) <$>+                  stk <- sGetCallStack sym+                  return $ VWord w (WordVal <$> (sWithCallStack sym stk (opw w lw rw)))+      | otherwise -> VSeq w <$> (join (zipSeqMap sym (loop a) <$>                                       (fromSeq "ringBinary left" l) <*>                                       (fromSeq "ringBinary right" r)))      TVStream a ->       -- streams-      VStream <$> (join (zipSeqMap (loop a) <$>+      VStream <$> (join (zipSeqMap sym (loop a) <$>                              (fromSeq "ringBinary left" l) <*>                              (fromSeq "ringBinary right" r)))      -- functions     TVFun _ ety ->-      return $ lam $ \ x -> loop' ety (fromVFun l x) (fromVFun r x)+      lam sym $ \ x -> loop' ety (fromVFun sym l x) (fromVFun sym r x)      -- tuples     TVTuple tys ->-      do ls <- mapM (sDelay sym Nothing) (fromVTuple l)-         rs <- mapM (sDelay sym Nothing) (fromVTuple r)+      do ls <- mapM (sDelay sym) (fromVTuple l)+         rs <- mapM (sDelay sym) (fromVTuple r)          return $ VTuple (zipWith3 loop' tys ls rs)      -- records     TVRec fs ->       do VRecord <$>             traverseRecordMap-              (\f fty -> sDelay sym Nothing (loop' fty (lookupRecord f l) (lookupRecord f r)))+              (\f fty -> sDelay sym (loop' fty (lookupRecord f l) (lookupRecord f r)))               fs      TVAbstract {} ->       evalPanic "ringBinary" ["Abstract type not in `Ring`"] +    TVNewtype {} ->+      evalPanic "ringBinary" ["Newtype not in `Ring`"]+ type UnaryWord sym = Integer -> SWord sym -> SEval sym (SWord sym)  @@ -282,30 +302,34 @@       -- words and finite sequences       | isTBit a -> do               wx <- fromVWord sym "ringUnary" v-              return $ VWord w (WordVal <$> opw w wx)-      | otherwise -> VSeq w <$> (mapSeqMap (loop a) =<< fromSeq "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)      TVStream a ->-      VStream <$> (mapSeqMap (loop a) =<< fromSeq "ringUnary" v)+      VStream <$> (mapSeqMap sym (loop a) =<< fromSeq "ringUnary" v)      -- functions     TVFun _ ety ->-      return $ lam $ \ y -> loop' ety (fromVFun v y)+      lam sym $ \ y -> loop' ety (fromVFun sym v y)      -- tuples     TVTuple tys ->-      do as <- mapM (sDelay sym Nothing) (fromVTuple v)+      do as <- mapM (sDelay sym) (fromVTuple v)          return $ VTuple (zipWith loop' tys as)      -- records     TVRec fs ->       VRecord <$>         traverseRecordMap-          (\f fty -> sDelay sym Nothing (loop' fty (lookupRecord f v)))+          (\f fty -> sDelay sym (loop' fty (lookupRecord f v)))           fs      TVAbstract {} -> evalPanic "ringUnary" ["Abstract type not in `Ring`"] +    TVNewtype {} -> evalPanic "ringUnary" ["Newtype not in `Ring`"]++ {-# SPECIALIZE ringNullary ::   Concrete ->   (Integer -> SEval Concrete (SWord Concrete)) ->@@ -346,30 +370,35 @@          TVSeq w a           -- words and finite sequences-          | isTBit a -> pure $ VWord w $ (WordVal <$> opw w)+          | isTBit a ->+             do stk <- sGetCallStack sym+                pure $ VWord w $ (WordVal <$> sWithCallStack sym stk (opw w))           | otherwise ->-             do v <- sDelay sym Nothing (loop a)-                pure $ VSeq w $ IndexSeqMap $ const v+             do v <- sDelay sym (loop a)+                pure $ VSeq w $ IndexSeqMap \_i -> v          TVStream a ->-             do v <- sDelay sym Nothing (loop a)-                pure $ VStream $ IndexSeqMap $ const v+             do v <- sDelay sym (loop a)+                pure $ VStream $ IndexSeqMap \_i -> v          TVFun _ b ->-             do v <- sDelay sym Nothing (loop b)-                pure $ lam $ const $ v+             do v <- sDelay sym (loop b)+                lam sym (const v)          TVTuple tys ->-             do xs <- mapM (sDelay sym Nothing . loop) tys+             do xs <- mapM (sDelay sym . loop) tys                 pure $ VTuple xs          TVRec fs ->-             do xs <- traverse (sDelay sym Nothing . loop) fs+             do xs <- traverse (sDelay sym . loop) fs                 pure $ VRecord xs          TVAbstract {} ->           evalPanic "ringNullary" ["Abstract type not in `Ring`"] +        TVNewtype {} ->+          evalPanic "ringNullary" ["Newtype not in `Ring`"]+ {-# SPECIALIZE integralBinary :: Concrete -> BinWord Concrete ->       (SInteger Concrete -> SInteger Concrete -> SEval Concrete (SInteger Concrete)) ->       Binary Concrete@@ -390,7 +419,8 @@       | isTBit a ->           do wl <- fromVWord sym "integralBinary left" l              wr <- fromVWord sym "integralBinary right" r-             return $ VWord w (WordVal <$> opw w wl wr)+             stk <- sGetCallStack sym+             return $ VWord w (WordVal <$> sWithCallStack sym stk (opw w wl wr))      _ -> evalPanic "integralBinary" [show ty ++ " not int class `Integral`"] @@ -398,15 +428,16 @@ --------------------------------------------------------------------------- -- Ring -{-# SPECIALIZE fromIntegerV :: Concrete -> GenValue Concrete+{-# SPECIALIZE fromIntegerV :: Concrete -> Prim Concrete   #-} -- | Convert an unbounded integer to a value in Ring-fromIntegerV :: Backend sym => sym -> GenValue sym+fromIntegerV :: Backend sym => sym -> Prim sym fromIntegerV sym =-  tlam $ \ a ->-  lam  $ \ v ->-  do i <- fromVInteger <$> v-     intV sym i a+  PTyPoly \a ->+  PFun    \v ->+  PPrim+    do i <- fromVInteger <$> v+       intV sym i a  {-# INLINE addV #-} addV :: Backend sym => sym -> Binary sym@@ -458,13 +489,14 @@     opw _w x y = wordDiv sym x y     opi x y = intDiv sym x y -{-# SPECIALIZE expV :: Concrete -> GenValue Concrete #-}-expV :: Backend sym => sym -> GenValue sym+{-# SPECIALIZE expV :: Concrete -> Prim Concrete #-}+expV :: Backend sym => sym -> Prim sym expV sym =-  tlam $ \aty ->-  tlam $ \ety ->-   lam $ \am -> return $-   lam $ \em ->+  PTyPoly \aty ->+  PTyPoly \ety ->+  PFun    \am ->+  PFun    \em ->+  PPrim      do a <- am         e <- em         case ety of@@ -522,12 +554,13 @@     opw _w x y = wordMod sym x y     opi x y = intMod sym x y -{-# SPECIALIZE toIntegerV :: Concrete -> GenValue Concrete #-}+{-# SPECIALIZE toIntegerV :: Concrete -> Prim Concrete #-} -- | Convert a word to a non-negative integer.-toIntegerV :: Backend sym => sym -> GenValue sym+toIntegerV :: Backend sym => sym -> Prim sym toIntegerV sym =-  tlam $ \a ->-  lam $ \v ->+  PTyPoly \a ->+  PFun    \v ->+  PPrim     case a of       TVSeq _w el | isTBit el ->         VInteger <$> (wordToInt sym =<< (fromVWord sym "toInteger" =<< v))@@ -537,11 +570,12 @@ ----------------------------------------------------------------------------- -- Field -{-# SPECIALIZE recipV :: Concrete -> GenValue Concrete #-}-recipV :: Backend sym => sym -> GenValue sym+{-# SPECIALIZE recipV :: Concrete -> Prim Concrete #-}+recipV :: Backend sym => sym -> Prim sym recipV sym =-  tlam $ \a ->-  lam $ \x ->+  PTyPoly \a ->+  PFun    \x ->+  PPrim     case a of       TVRational -> VRational <$> (rationalRecip sym . fromVRational =<< x)       TVFloat e p ->@@ -552,12 +586,13 @@       TVIntMod m -> VInteger <$> (znRecip sym m . fromVInteger =<< x)       _ -> evalPanic "recip"  [show a ++ "is not a Field"] -{-# SPECIALIZE fieldDivideV :: Concrete -> GenValue Concrete #-}-fieldDivideV :: Backend sym => sym -> GenValue sym+{-# SPECIALIZE fieldDivideV :: Concrete -> Prim Concrete #-}+fieldDivideV :: Backend sym => sym -> Prim sym fieldDivideV sym =-  tlam $ \a ->-  lam $ \x -> return $-  lam $ \y ->+  PTyPoly \a ->+  PFun    \x ->+  PFun    \y ->+  PPrim     case a of       TVRational ->         do x' <- fromVRational <$> x@@ -656,27 +691,27 @@ -- Bitvector signed div and modulus  {-# INLINE lg2V #-}-lg2V :: Backend sym => sym -> GenValue sym+lg2V :: Backend sym => sym -> Prim sym lg2V sym =-  nlam $ \(finNat' -> w) ->-  wlam sym $ \x -> return $-  VWord w (WordVal <$> wordLg2 sym x)+  PFinPoly \w ->+  PWordFun \x ->+  PVal (VWord w (WordVal <$> wordLg2 sym x)) -{-# SPECIALIZE sdivV :: Concrete -> GenValue Concrete #-}-sdivV :: Backend sym => sym -> GenValue sym+{-# SPECIALIZE sdivV :: Concrete -> Prim Concrete #-}+sdivV :: Backend sym => sym -> Prim sym sdivV sym =-  nlam $ \(finNat' -> w) ->-  wlam sym $ \x -> return $-  wlam sym $ \y -> return $-  VWord w (WordVal <$> wordSignedDiv sym x y)+  PFinPoly \w ->+  PWordFun \x ->+  PWordFun \y ->+  PVal (VWord w (WordVal <$> wordSignedDiv sym x y)) -{-# SPECIALIZE smodV :: Concrete -> GenValue Concrete #-}-smodV :: Backend sym => sym -> GenValue sym+{-# SPECIALIZE smodV :: Concrete -> Prim Concrete #-}+smodV :: Backend sym => sym -> Prim sym smodV sym  =-  nlam $ \(finNat' -> w) ->-  wlam sym $ \x -> return $-  wlam sym $ \y -> return $-  VWord w (WordVal <$> wordSignedMod sym x y)+  PFinPoly \w ->+  PWordFun \x ->+  PWordFun \y ->+  PVal (VWord w (WordVal <$> wordSignedMod sym x y))  -- Cmp ------------------------------------------------------------------------- @@ -733,6 +768,9 @@         TVAbstract {} -> evalPanic "cmpValue"                           [ "Abstract type not in `Cmp`" ] +        TVNewtype {} -> evalPanic "cmpValue"+                          [ "Newtype not in `Cmp`" ]+     cmpValues (t : ts) (x1 : xs1) (x2 : xs2) k =       do x1' <- x1          x2' <- x2@@ -879,30 +917,32 @@   TVSeq w ety       | isTBit ety -> pure $ word sym w 0       | otherwise  ->-           do z <- sDelay sym Nothing (zeroV sym ety)-              pure $ VSeq w (IndexSeqMap $ const z)+           do z <- sDelay sym (zeroV sym ety)+              pure $ VSeq w (IndexSeqMap \_i -> z)    TVStream ety ->-     do z <- sDelay sym Nothing (zeroV sym ety)-        pure $ VStream (IndexSeqMap $ const z)+     do z <- sDelay sym (zeroV sym ety)+        pure $ VStream (IndexSeqMap \_i -> z)    -- functions   TVFun _ bty ->-     do z <- sDelay sym Nothing (zeroV sym bty)-        pure $ lam (const z)+     do z <- sDelay sym (zeroV sym bty)+        lam sym (const z)    -- tuples   TVTuple tys ->-      do xs <- mapM (sDelay sym Nothing . zeroV sym) tys+      do xs <- mapM (sDelay sym . zeroV sym) tys          pure $ VTuple xs    -- records   TVRec fields ->-      do xs <- traverse (sDelay sym Nothing . zeroV sym) fields+      do xs <- traverse (sDelay sym . zeroV sym) fields          pure $ VRecord xs    TVAbstract {} -> evalPanic "zeroV" [ "Abstract type not in `Zero`" ] +  TVNewtype {} -> evalPanic "zeroV" [ "Newtype not in `Zero`" ]+ --  | otherwise = evalPanic "zeroV" ["invalid type for zero"]  {-# INLINE joinWordVal #-}@@ -936,7 +976,7 @@  where  loop :: SEval sym (WordValue sym) -> [SEval sym (GenValue sym)] -> SEval sym (GenValue sym)  loop !wv [] =-    VWord (nParts * nEach) <$> sDelay sym Nothing wv+    VWord (nParts * nEach) <$> sDelay sym wv  loop !wv (w : ws) =     w >>= \case       VWord _ w' ->@@ -1038,24 +1078,24 @@   case back of      Nat rightWidth | aBit -> do-          ws <- sDelay sym Nothing (splitWordVal sym leftWidth rightWidth =<< fromWordVal "splitAtV" val)+          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 Nothing (fromSeq "splitAtV" val)-       ls <- sDelay sym Nothing (fst . splitSeqMap leftWidth <$> vs)-       rs <- sDelay sym Nothing (snd . splitSeqMap leftWidth <$> vs)+       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 Nothing (fromSeq "splitAtV" val)-       ls <- sDelay sym Nothing (fst . splitSeqMap leftWidth <$> vs)-       rs <- sDelay sym Nothing (snd . splitSeqMap leftWidth <$> vs)+       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                        ]@@ -1093,19 +1133,20 @@ {-# INLINE ecSplitV #-}  -- | Split implementation.-ecSplitV :: Backend sym => sym -> GenValue sym+ecSplitV :: Backend sym => sym -> Prim sym ecSplitV sym =-  nlam $ \ parts ->-  nlam $ \ each  ->-  tlam $ \ a     ->-  lam  $ \ val ->+  PNumPoly \parts ->+  PNumPoly \each ->+  PTyPoly  \a ->+  PFun     \val ->+  PPrim     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 Nothing (fromSeq "ecSplitV" =<< val)+          val' <- sDelay sym (fromSeq "ecSplitV" =<< val)           return $ VStream $ IndexSeqMap $ \i ->             return $ VWord e $ return $ LargeBitsVal e $ IndexSeqMap $ \j ->               let idx = i*e + toInteger j@@ -1113,13 +1154,13 @@                       xs <- val'                       lookupSeqMap xs idx        (Nat p, Nat e) -> do-          val' <- sDelay sym Nothing (fromSeq "ecSplitV" =<< val)+          val' <- sDelay sym (fromSeq "ecSplitV" =<< 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 Nothing (fromSeq "ecSplitV" =<< val)+          val' <- sDelay sym (fromSeq "ecSplitV" =<< val)           return $ VStream $ IndexSeqMap $ \i ->             return $ VSeq e $ IndexSeqMap $ \j -> do               xs <- val'@@ -1157,7 +1198,8 @@   | 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 ->-         do ys <- flip lookupSeqMap (toInteger ai) =<< fromSeq "transposeV" xs+         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)@@ -1166,7 +1208,8 @@   | isTBit c, Inf <- a = -- [inf][b]Bit -> [b][inf]Bit       return $ bseq $ IndexSeqMap $ \bi ->         return $ VStream $ IndexSeqMap $ \ai ->-         do ys <- flip lookupSeqMap ai =<< fromSeq "transposeV" xs+         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)@@ -1175,8 +1218,9 @@   | otherwise = -- [a][b]c -> [b][a]c       return $ bseq $ IndexSeqMap $ \bi ->         return $ aseq $ IndexSeqMap $ \ai -> do-          ys  <- flip lookupSeqMap ai =<< fromSeq "transposeV 1" xs-          z   <- flip lookupSeqMap bi =<< fromSeq "transposeV 2" ys+          xs' <- fromSeq "transposeV 1" xs+          ys  <- fromSeq "transposeV 2" =<< lookupSeqMap xs' ai+          z   <- lookupSeqMap ys bi           return z   where@@ -1206,7 +1250,7 @@   return $ VWord (m+n) (join (joinWordVal sym <$> l <*> r))  ccatV sym _front _back _elty (VWord m l) (VStream r) = do-  l' <- sDelay sym Nothing l+  l' <- sDelay sym l   return $ VStream $ IndexSeqMap $ \i ->     if i < m then       VBit <$> (flip (indexWordValue sym) i =<< l')@@ -1214,8 +1258,8 @@       lookupSeqMap r (i-m)  ccatV sym front back elty l r = do-       l'' <- sDelay sym Nothing (fromSeq "ccatV left" l)-       r'' <- sDelay sym Nothing (fromSeq "ccatV right" r)+       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@@ -1238,7 +1282,7 @@ wordValLogicOp _sym _ wop (WordVal w1) (WordVal w2) = WordVal <$> wop w1 w2  wordValLogicOp sym bop _ w1 w2 = LargeBitsVal (wordValueSize sym w1) <$> zs-     where zs = memoMap $ IndexSeqMap $ \i -> join (op <$> (lookupSeqMap xs i) <*> (lookupSeqMap ys i))+     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))@@ -1281,7 +1325,7 @@     TVSeq w aty          -- words          | isTBit aty-              -> do v <- sDelay sym Nothing $ join+              -> do v <- sDelay sym $ join                             (wordValLogicOp sym opb opw <$>                                     fromWordVal "logicBinary l" l <*>                                     fromWordVal "logicBinary r" r)@@ -1289,41 +1333,45 @@           -- finite sequences          | otherwise -> VSeq w <$>-                           (join (zipSeqMap (loop aty) <$>+                           (join (zipSeqMap sym (loop aty) <$>                                     (fromSeq "logicBinary left" l)                                     <*> (fromSeq "logicBinary right" r)))      TVStream aty ->-        VStream <$> (join (zipSeqMap (loop aty) <$>+        VStream <$> (join (zipSeqMap sym (loop aty) <$>                           (fromSeq "logicBinary left" l) <*>                           (fromSeq "logicBinary right" r)))      TVTuple etys -> do-        ls <- mapM (sDelay sym Nothing) (fromVTuple l)-        rs <- mapM (sDelay sym Nothing) (fromVTuple r)+        ls <- mapM (sDelay sym) (fromVTuple l)+        rs <- mapM (sDelay sym) (fromVTuple r)         return $ VTuple $ zipWith3 loop' etys ls rs      TVFun _ bty ->-        return $ lam $ \ a -> loop' bty (fromVFun l a) (fromVFun r a)+        lam sym $ \ a -> loop' bty (fromVFun sym l a) (fromVFun sym r a)      TVRec fields ->       VRecord <$>         traverseRecordMap-          (\f fty -> sDelay sym Nothing (loop' fty (lookupRecord f l) (lookupRecord f r)))+          (\f fty -> sDelay sym (loop' fty (lookupRecord f l) (lookupRecord f r)))           fields      TVAbstract {} -> evalPanic "logicBinary"                         [ "Abstract type not in `Logic`" ] +    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 bop _ (LargeBitsVal n xs) = LargeBitsVal n <$> mapSeqMap f xs+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 ::@@ -1357,32 +1405,33 @@     TVSeq w ety          -- words          | isTBit ety-              -> do v <- sDelay sym Nothing (wordValUnaryOp opb opw =<< fromWordVal "logicUnary" val)+              -> do v <- sDelay sym (wordValUnaryOp sym opb opw =<< fromWordVal "logicUnary" val)                     return $ VWord w v           -- finite sequences          | otherwise-              -> VSeq w <$> (mapSeqMap (loop ety) =<< fromSeq "logicUnary" val)+              -> VSeq w <$> (mapSeqMap sym (loop ety) =<< fromSeq "logicUnary" val)           -- streams     TVStream ety ->-         VStream <$> (mapSeqMap (loop ety) =<< fromSeq "logicUnary" val)+         VStream <$> (mapSeqMap sym (loop ety) =<< fromSeq "logicUnary" val)      TVTuple etys ->-      do as <- mapM (sDelay sym Nothing) (fromVTuple val)+      do as <- mapM (sDelay sym) (fromVTuple val)          return $ VTuple (zipWith loop' etys as)      TVFun _ bty ->-      return $ lam $ \ a -> loop' bty (fromVFun val a)+      lam sym $ \ a -> loop' bty (fromVFun sym val a)      TVRec fields ->       VRecord <$>         traverseRecordMap-          (\f fty -> sDelay sym Nothing (loop' fty (lookupRecord f val)))+          (\f fty -> sDelay sym (loop' fty (lookupRecord f val)))           fields      TVAbstract {} -> evalPanic "logicUnary" [ "Abstract type not in `Logic`" ] +    TVNewtype {} -> evalPanic "logicUnary" [ "Newtype not in `Logic`" ]  {-# SPECIALIZE bitsValueLessThan ::   Concrete ->@@ -1471,14 +1520,15 @@   (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)) ->-  GenValue sym+  Prim sym indexPrim sym int_op bits_op word_op =-  nlam $ \ len  ->-  tlam $ \ eltTy ->-  tlam $ \ ix ->-   lam $ \ xs  -> return $-   lam $ \ idx  -> do-      vs <- xs >>= \case+  PNumPoly \len ->+  PTyPoly  \eltTy ->+  PTyPoly  \ix ->+  PFun     \xs ->+  PFun     \idx ->+  PPrim+   do vs <- xs >>= \case                VWord _ w  -> w >>= \w' -> return $ IndexSeqMap (\i -> VBit <$> indexWordValue sym w' i)                VSeq _ vs  -> return vs                VStream vs -> return vs@@ -1486,7 +1536,7 @@       idx' <- asIndex sym "index" ix =<< idx       assertIndexInBounds sym len idx'       case idx' of-        Left i                    -> int_op len eltTy vs ix i+        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) @@ -1497,31 +1547,33 @@   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)) ->-  GenValue sym+  Prim sym updatePrim sym updateWord updateSeq =-  nlam $ \len ->-  tlam $ \eltTy ->-  tlam $ \ix ->-  lam $ \xs  -> return $-  lam $ \idx -> return $-  lam $ \val -> do-    idx' <- asIndex sym "update" ix =<< idx-    assertIndexInBounds sym len idx'-    xs >>= \case-      VWord l w  -> do w' <- sDelay sym Nothing 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"]+  PNumPoly \len ->+  PTyPoly  \eltTy ->+  PTyPoly  \ix ->+  PFun     \xs ->+  PFun     \idx ->+  PFun     \val ->+  PPrim+   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"]  {-# INLINE fromToV #-}  -- @[ 0 .. 10 ]@-fromToV :: Backend sym => sym -> GenValue sym+fromToV :: Backend sym => sym -> Prim sym fromToV sym =-  nlam $ \ first ->-  nlam $ \ lst   ->-  tlam $ \ ty    ->+  PNumPoly \first ->+  PNumPoly \lst ->+  PTyPoly  \ty ->+  PVal     let !f = mkLit sym ty in     case (first, lst) of       (Nat first', Nat lst') ->@@ -1529,16 +1581,32 @@         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 -> GenValue sym+fromThenToV :: Backend sym => sym -> Prim sym fromThenToV sym =-  nlam $ \ first ->-  nlam $ \ next  ->-  nlam $ \ lst   ->-  tlam $ \ ty    ->-  nlam $ \ len   ->+  PNumPoly \first ->+  PNumPoly \next  ->+  PNumPoly \lst   ->+  PTyPoly  \ty    ->+  PNumPoly \len   ->+  PVal     let !f = mkLit sym ty in     case (first, next, lst, len) of       (Nat first', Nat next', Nat _lst', Nat len') ->@@ -1547,31 +1615,33 @@       _ -> evalPanic "fromThenToV" ["invalid arguments"]  {-# INLINE infFromV #-}-infFromV :: Backend sym => sym -> GenValue sym+infFromV :: Backend sym => sym -> Prim sym infFromV sym =-  tlam $ \ ty ->-  lam  $ \ x ->-  do mx <- sDelay sym Nothing x-     return $ VStream $ IndexSeqMap $ \i ->-       do x' <- mx-          i' <- integerLit sym i-          addV sym ty x' =<< intV sym i' ty+  PTyPoly \ty ->+  PFun    \x ->+  PPrim+    do mx <- sDelay sym x+       return $ VStream $ IndexSeqMap $ \i ->+         do x' <- mx+            i' <- integerLit sym i+            addV sym ty x' =<< intV sym i' ty  {-# INLINE infFromThenV #-}-infFromThenV :: Backend sym => sym -> GenValue sym+infFromThenV :: Backend sym => sym -> Prim sym infFromThenV sym =-  tlam $ \ ty ->-  lam $ \ first -> return $-  lam $ \ next ->-  do mxd <- sDelay sym Nothing-             (do x <- first-                 y <- next-                 d <- subV sym ty y x-                 pure (x,d))-     return $ VStream $ IndexSeqMap $ \i -> do-       (x,d) <- mxd-       i' <- integerLit sym i-       addV sym ty x =<< mulV sym ty d =<< intV sym i' ty+  PTyPoly \ty ->+  PFun    \first ->+  PFun    \next ->+  PPrim+    do mxd <- sDelay sym+               (do x <- first+                   y <- next+                   d <- subV sym ty y x+                   pure (x,d))+       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 --------------------------------------------------- @@ -1596,7 +1666,7 @@      | otherwise     = do x_shft <- shift_op x (2 ^ length bs)-         x' <- memoMap (mergeSeqMap sym b x_shft x)+         x' <- memoMap sym (mergeSeqMap sym b x_shft x)          go x' bs  {-# INLINE shiftLeftReindex #-}@@ -1670,13 +1740,14 @@      {- ^ reindexing operation for positive indices (sequence size, starting index, shift amount -} ->   (Nat' -> Integer -> Integer -> Maybe Integer)      {- ^ reindexing operation for negative indices (sequence size, starting index, shift amount -} ->-  GenValue sym+  Prim sym logicShift sym nm shrinkRange wopPos wopNeg reindexPos reindexNeg =-  nlam $ \m ->-  tlam $ \ix ->-  tlam $ \a ->-  VFun $ \xs -> return $-  VFun $ \y ->+  PNumPoly \m ->+  PTyPoly  \ix ->+  PTyPoly  \a ->+  PFun     \xs ->+  PFun     \y ->+  PPrim     do xs' <- xs        y' <- asIndex sym "shift" ix =<< y        case y' of@@ -1701,7 +1772,7 @@    SEval sym (GenValue sym) intShifter sym nm wop reindex m ix a xs idx =    do let shiftOp vs shft =-              memoMap $ IndexSeqMap $ \i ->+              memoMap sym $ IndexSeqMap $ \i ->                 case reindex m i shft of                   Nothing -> zeroV sym a                   Just i' -> lookupSeqMap vs i'@@ -1737,7 +1808,7 @@    SEval sym (GenValue sym) wordShifter sym nm wop reindex m a xs idx =   let shiftOp vs shft =-          memoMap $ IndexSeqMap $ \i ->+          memoMap sym $ IndexSeqMap $ \i ->             case reindex m i shft of               Nothing -> zeroV sym a               Just i' -> lookupSeqMap vs i'@@ -1789,37 +1860,38 @@   TValue ->   String ->   SEval sym (GenValue sym)-errorV sym ty msg = case ty of-  -- bits-  TVBit -> cryUserError sym msg-  TVInteger -> cryUserError sym msg-  TVIntMod _ -> cryUserError sym msg-  TVRational -> cryUserError sym msg-  TVArray{} -> cryUserError sym msg-  TVFloat {} -> cryUserError sym msg+errorV sym ty0 msg =+     do stk <- sGetCallStack sym+        loop stk ty0+  where+  err stk = sWithCallStack sym stk (cryUserError sym msg) -  -- sequences-  TVSeq w ety-     | isTBit ety -> return $ VWord w $ return $ LargeBitsVal w $ IndexSeqMap $ \_ -> cryUserError sym msg-     | otherwise  -> return $ VSeq w (IndexSeqMap $ \_ -> errorV sym ety msg)+  loop stk = \case+       TVBit -> err stk+       TVInteger -> err stk+       TVIntMod _ -> err stk+       TVRational -> err stk+       TVArray{} -> err stk+       TVFloat {} -> err stk -  TVStream ety ->-    return $ VStream (IndexSeqMap $ \_ -> errorV sym ety msg)+       -- sequences+       TVSeq w ety+          | isTBit ety -> return $ VWord w $ return $ LargeBitsVal w $ IndexSeqMap $ \_ -> err stk+          | otherwise  -> return $ VSeq w $ IndexSeqMap $ \_ -> loop stk ety -  -- functions-  TVFun _ bty ->-    return $ lam (\ _ -> errorV sym bty msg)+       TVStream ety -> return $ VStream $ IndexSeqMap $ \_ -> loop stk ety -  -- tuples-  TVTuple tys ->-    return $ VTuple (map (\t -> errorV sym t msg) tys)+       -- functions+       TVFun _ bty -> lam sym (\ _ -> loop stk bty) -  -- records-  TVRec fields ->-    return $ VRecord $ fmap (\t -> errorV sym t msg) $ fields+       -- tuples+       TVTuple tys -> return $ VTuple (map (\t -> loop stk t) tys) -  TVAbstract {} -> cryUserError sym msg+       -- records+       TVRec fields -> return $ VRecord $ fmap (\t -> loop stk t) $ fields +       TVAbstract {} -> err stk+       TVNewtype {} -> err stk  {-# INLINE valueToChar #-} @@ -1862,7 +1934,7 @@ mergeWord sym c (WordVal w1) (WordVal w2) =   WordVal <$> iteWord sym c w1 w2 mergeWord sym c w1 w2 =-  LargeBitsVal (wordValueSize sym w1) <$> memoMap (mergeSeqMap sym c (asBitsMap sym w1) (asBitsMap sym w2))+  LargeBitsVal (wordValueSize sym w1) <$> memoMap sym (mergeSeqMap sym c (asBitsMap sym w1) (asBitsMap sym w2))  {-# INLINE mergeWord' #-} mergeWord' :: Backend sym =>@@ -1900,11 +1972,12 @@     (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 (mergeSeqMap sym c vs1 vs2)-    (VStream vs1 , VStream vs2 ) -> VStream <$> memoMap (mergeSeqMap sym c vs1 vs2)-    (VFun f1     , VFun f2     ) -> pure $ VFun $ \x -> mergeValue' sym c (f1 x) (f2 x)-    (VPoly f1    , VPoly f2    ) -> pure $ VPoly $ \x -> mergeValue' sym c (f1 x) (f2 x)+    (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" ] @@ -1921,53 +1994,55 @@   -foldlV :: Backend sym => sym -> GenValue sym+foldlV :: Backend sym => sym -> Prim sym foldlV sym =-  ilam $ \_n ->-  tlam $ \_a ->-  tlam $ \_b ->-  lam $ \f -> pure $-  lam $ \z -> pure $-  lam $ \v ->-    v >>= \case+  PNumPoly \_n ->+  PTyPoly  \_a ->+  PTyPoly  \_b ->+  PFun     \f ->+  PFun     \z ->+  PStrict  \v ->+  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)       _ -> panic "Cryptol.Eval.Generic.foldlV" ["Expected finite sequence"]   where   go0 _f a [] = a   go0 f a bs =-    do f' <- fromVFun <$> f+    do f' <- fromVFun sym <$> f        go1 f' a bs    go1 _f a [] = a   go1 f a (b:bs) =-    do f' <- fromVFun <$> (f a)+    do f' <- fromVFun sym <$> (f a)        go1 f (f' b) bs -foldl'V :: Backend sym => sym -> GenValue sym+foldl'V :: Backend sym => sym -> Prim sym foldl'V sym =-  ilam $ \_n ->-  tlam $ \_a ->-  tlam $ \_b ->-  lam $ \f -> pure $-  lam $ \z -> pure $-  lam $ \v ->-    v >>= \case+  PNumPoly \_n ->+  PTyPoly  \_a ->+  PTyPoly  \_b ->+  PFun     \f ->+  PFun     \z ->+  PStrict  \v ->+  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)       _ -> panic "Cryptol.Eval.Generic.foldlV" ["Expected finite sequence"]   where   go0 _f a [] = a   go0 f a bs =-    do f' <- fromVFun <$> f-       a' <- sDelay sym Nothing a+    do f' <- fromVFun sym <$> f+       a' <- sDelay sym a        forceValue =<< a'        go1 f' a' bs    go1 _f a [] = a   go1 f a (b:bs) =-    do f' <- fromVFun <$> (f a)-       a' <- sDelay sym Nothing (f' b)+    do f' <- fromVFun sym <$> (f a)+       a' <- sDelay sym (f' b)        forceValue =<< a'        go1 f a' bs @@ -1994,14 +2069,15 @@ -------------------------------------------------------------------------------- -- Experimental parallel primitives -parmapV :: Backend sym => sym -> GenValue sym+parmapV :: Backend sym => sym -> Prim sym parmapV sym =-  tlam $ \_a ->-  tlam $ \_b ->-  ilam $ \_n ->-  lam $ \f -> pure $-  lam $ \xs ->-    do f' <- fromVFun <$> f+  PTyPoly \_a ->+  PTyPoly \_b ->+  PFinPoly \_n ->+  PFun \f ->+  PFun \xs ->+  PPrim+    do f' <- fromVFun sym <$> f        xs' <- xs        case xs' of           VWord n w ->@@ -2022,25 +2098,35 @@   SeqMap sym ->   SEval sym (SeqMap sym) sparkParMap sym f n m =-  finiteSeqMap sym <$> mapM (sSpark sym . g) (enumerateSeqMap n m)+  finiteSeqMap <$> mapM (sSpark sym . g) (enumerateSeqMap n m)  where  g x =-   do z <- sDelay sym Nothing (f x)+   do z <- sDelay sym (f x)       forceValue =<< z       z  -------------------------------------------------------------------------------- -- Floating Point Operations +-- | A helper for definitng floating point constants.+fpConst ::+  Backend sym =>+  (Integer -> Integer -> SEval sym (SFloat sym)) ->+  Prim sym+fpConst mk =+  PFinPoly \e ->+  PNumPoly \ ~(Nat p) ->+  PPrim (VFloat <$> mk e p)+ -- | Make a Cryptol value for a binary arithmetic function.-fpBinArithV :: Backend sym => sym -> FPArith2 sym -> GenValue sym+fpBinArithV :: Backend sym => sym -> FPArith2 sym -> Prim sym fpBinArithV sym fun =-  ilam \_ ->-  ilam \_ ->-  wlam sym \r ->-  pure $ flam \x ->-  pure $ flam \y ->-  VFloat <$> fun sym r x y+  PFinPoly  \_e ->+  PFinPoly  \_p ->+  PWordFun  \r ->+  PFloatFun \x ->+  PFloatFun \y ->+  PPrim (VFloat <$> fun sym r x y)  -- | Rounding mode used in FP operations that do not specify it explicitly. fpRndMode, fpRndRNE, fpRndRNA, fpRndRTP, fpRndRTN, fpRndRTZ ::@@ -2051,3 +2137,266 @@ fpRndRTP sym = wordLit sym 3 2 {- to +inf -} fpRndRTN sym = wordLit sym 3 3 {- to -inf -} fpRndRTZ sym = wordLit sym 3 4 {- to 0    -}+++{-# SPECIALIZE genericFloatTable :: Concrete -> Map PrimIdent (Prim Concrete) #-}++genericFloatTable :: Backend sym => sym -> Map PrimIdent (Prim sym)+genericFloatTable sym =+  let (~>) = (,) in+  Map.fromList $ map (\(n, v) -> (floatPrim n, v))+    [ "fpNaN"       ~> fpConst (fpNaN sym)+    , "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+    , "=.="         ~> PFinPoly \_ -> PFinPoly \_ -> PFloatFun \x -> PFloatFun \y ->+                       PPrim (VBit <$> fpLogicalEq sym x y)++    , "fpIsNaN"     ~> PFinPoly \_ -> PFinPoly \_ -> PFloatFun \x ->+                       PPrim (VBit <$> fpIsNaN sym x)+    , "fpIsInf"     ~> PFinPoly \_ -> PFinPoly \_ -> PFloatFun \x ->+                       PPrim (VBit <$> fpIsInf sym x)+    , "fpIsZero"    ~> PFinPoly \_ -> PFinPoly \_ -> PFloatFun \x ->+                       PPrim (VBit <$> fpIsZero sym x)+    , "fpIsNeg"     ~> PFinPoly \_ -> PFinPoly \_ -> PFloatFun \x ->+                       PPrim (VBit <$> fpIsNeg sym x)+    , "fpIsNormal"  ~> PFinPoly \_ -> PFinPoly \_ -> PFloatFun \x ->+                       PPrim (VBit <$> fpIsNorm sym x)+    , "fpIsSubnormal" ~> PFinPoly \_ -> PFinPoly \_ -> PFloatFun \x ->+                         PPrim (VBit <$> fpIsSubnorm sym x)++    , "fpAdd"       ~> fpBinArithV sym fpPlus+    , "fpSub"       ~> fpBinArithV sym fpMinus+    , "fpMul"       ~> fpBinArithV sym fpMult+    , "fpDiv"       ~> fpBinArithV sym fpDiv+    , "fpFMA"       ~> PFinPoly \_ -> PFinPoly \_ -> PWordFun \r ->+                       PFloatFun \x -> PFloatFun \y -> PFloatFun \z ->+                       PPrim (VFloat <$> fpFMA sym r x y z)++    , "fpAbs"       ~> PFinPoly \_ -> PFinPoly \_ ->+                       PFloatFun \x ->+                       PPrim (VFloat <$> fpAbs sym x)++    , "fpSqrt"      ~> PFinPoly \_ -> PFinPoly \_ ->+                       PWordFun \r -> PFloatFun \x ->+                       PPrim (VFloat <$> fpSqrt sym r x)++    , "fpToRational" ~>+       PFinPoly \_e -> PFinPoly \_p -> PFloatFun \x ->+       PPrim (VRational <$> fpToRational sym x)++    , "fpFromRational" ~>+       PFinPoly \e -> PFinPoly \p -> PWordFun \r -> PFun \x ->+       PPrim+         do rat <- fromVRational <$> x+            VFloat <$> fpFromRational sym e p r rat++    ]+++{-# SPECIALIZE genericPrimTable :: Concrete -> IO EvalOpts -> Map PrimIdent (Prim Concrete) #-}++genericPrimTable :: Backend sym => sym -> IO EvalOpts -> Map PrimIdent (Prim sym)+genericPrimTable sym getEOpts =+  Map.fromList $ map (\(n, v) -> (prelPrim n, v))++  [ -- Literals+    ("True"       , PVal $ VBit (bitLit sym True))+  , ("False"      , PVal $ VBit (bitLit sym False))+  , ("number"     , {-# SCC "Prelude::number" #-}+                    ecNumberV sym)+  , ("ratio"      , {-# SCC "Prelude::ratio" #-}+                    ratioV sym)+  , ("fraction"   , ecFractionV sym)++    -- Zero+  , ("zero"       , {-# SCC "Prelude::zero" #-}+                    PTyPoly \ty ->+                    PPrim (zeroV sym ty))++    -- Logic+  , ("&&"         , {-# SCC "Prelude::(&&)" #-}+                    binary (andV sym))+  , ("||"         , {-# SCC "Prelude::(||)" #-}+                    binary (orV sym))+  , ("^"          , {-# SCC "Prelude::(^)" #-}+                    binary (xorV sym))+  , ("complement" , {-# SCC "Prelude::complement" #-}+                    unary  (complementV sym))++    -- Ring+  , ("fromInteger", {-# SCC "Prelude::fromInteger" #-}+                    fromIntegerV sym)+  , ("+"          , {-# SCC "Prelude::(+)" #-}+                    binary (addV sym))+  , ("-"          , {-# SCC "Prelude::(-)" #-}+                    binary (subV sym))+  , ("*"          , {-# SCC "Prelude::(*)" #-}+                    binary (mulV sym))+  , ("negate"     , {-# SCC "Prelude::negate" #-}+                    unary (negateV sym))++    -- Integral+  , ("toInteger"  , {-# SCC "Prelude::toInteger" #-}+                    toIntegerV sym)+  , ("/"          , {-# SCC "Prelude::(/)" #-}+                    binary (divV sym))+  , ("%"          , {-# SCC "Prelude::(%)" #-}+                    binary (modV sym))+  , ("^^"         , {-# SCC "Prelude::(^^)" #-}+                    expV sym)+  , ("infFrom"    , {-# SCC "Prelude::infFrom" #-}+                    infFromV sym)+  , ("infFromThen", {-# SCC "Prelude::infFromThen" #-}+                    infFromThenV sym)++    -- Field+  , ("recip"      , {-# SCC "Prelude::recip" #-}+                    recipV sym)+  , ("/."         , {-# SCC "Prelude::(/.)" #-}+                    fieldDivideV sym)++    -- Round+  , ("floor"      , {-# SCC "Prelude::floor" #-}+                    unary (floorV sym))+  , ("ceiling"    , {-# SCC "Prelude::ceiling" #-}+                    unary (ceilingV sym))+  , ("trunc"      , {-# SCC "Prelude::trunc" #-}+                    unary (truncV sym))+  , ("roundAway"  , {-# SCC "Prelude::roundAway" #-}+                    unary (roundAwayV sym))+  , ("roundToEven", {-# SCC "Prelude::roundToEven" #-}+                    unary (roundToEvenV sym))++    -- Bitvector specific operations+  , ("/$"         , {-# SCC "Prelude::(/$)" #-}+                    sdivV sym)+  , ("%$"         , {-# SCC "Prelude::(%$)" #-}+                    smodV sym)+  , ("lg2"        , {-# SCC "Prelude::lg2" #-}+                    lg2V sym)++    -- Cmp+  , ("<"          , {-# SCC "Prelude::(<)" #-}+                    binary (lessThanV sym))+  , (">"          , {-# SCC "Prelude::(>)" #-}+                    binary (greaterThanV sym))+  , ("<="         , {-# SCC "Prelude::(<=)" #-}+                    binary (lessThanEqV sym))+  , (">="         , {-# SCC "Prelude::(>=)" #-}+                    binary (greaterThanEqV sym))+  , ("=="         , {-# SCC "Prelude::(==)" #-}+                    binary (eqV sym))+  , ("!="         , {-# SCC "Prelude::(!=)" #-}+                    binary (distinctV sym))++    -- SignedCmp+  , ("<$"         , {-# SCC "Prelude::(<$)" #-}+                    binary (signedLessThanV sym))++    -- Finite enumerations+  , ("fromTo"     , {-# SCC "Prelude::fromTo" #-}+                    fromToV sym)++  , ("fromThenTo" , {-# SCC "Prelude::fromThenTo" #-}+                    fromThenToV sym)++  , ("fromToLessThan"+                  , {-# SCC "Prelude::fromToLessThan" #-}+                    fromToLessThanV sym)++    -- Sequence manipulations+  , ("#"          , {-# SCC "Prelude::(#)" #-}+                    PFinPoly \front ->+                    PNumPoly \back  ->+                    PTyPoly  \elty  ->+                    PFun \l ->+                    PFun \r ->+                    PPrim (join (ccatV sym (Nat front) back elty <$> l <*> r)))++  , ("join"       , {-# SCC "Prelude::join" #-}+                    PNumPoly \parts ->+                    PFinPoly \each  ->+                    PTyPoly  \a     ->+                    PStrict  \x   ->+                    PPrim $ joinV sym parts each a x)++  , ("split"      , {-# SCC "Prelude::split" #-}+                    ecSplitV sym)++  , ("splitAt"    , {-# SCC "Prelude::splitAt" #-}+                    PNumPoly \front ->+                    PNumPoly \back  ->+                    PTyPoly  \a     ->+                    PStrict  \x   ->+                    PPrim $ splitAtV sym front back a x)++  , ("reverse"    , {-# SCC "Prelude::reverse" #-}+                    PFinPoly \_a ->+                    PTyPoly  \_b ->+                    PStrict  \xs ->+                    PPrim $ reverseV sym xs)++  , ("transpose"  , {-# SCC "Prelude::transpose" #-}+                    PNumPoly \a ->+                    PNumPoly \b ->+                    PTyPoly  \c ->+                    PStrict  \xs ->+                    PPrim $ transposeV sym a b c xs)++    -- Misc++    -- {at,len} (fin len) => [len][8] -> at+  , ("error"      , {-# SCC "Prelude::error" #-}+                     PTyPoly  \a ->+                     PFinPoly \_ ->+                     PStrict  \s ->+                     PPrim (errorV sym a =<< valueToString sym s))++  , ("trace"       , {-# SCC "Prelude::trace" #-}+                     PNumPoly \_n ->+                     PTyPoly  \_a ->+                     PTyPoly  \_b ->+                     PFun     \s ->+                     PFun     \x ->+                     PFun     \y ->+                     PPrim+                      do msg <- valueToString sym =<< s+                         EvalOpts { evalPPOpts, evalLogger } <- liftIO getEOpts+                         doc <- ppValue sym evalPPOpts =<< x+                         liftIO $ logPrint evalLogger+                             $ if null msg then doc else text msg <+> doc+                         y)++  , ("random"      , {-# SCC "Prelude::random" #-}+                     PTyPoly  \a ->+                     PWordFun \x ->+                     PPrim+                       case wordAsLit sym x of+                         Just (_,i)  -> randomV sym a i+                         Nothing -> liftIO (X.throw (UnsupportedSymbolicOp "random")))++  , ("foldl"      , {-# SCC "Prelude::foldl" #-}+                    foldlV sym)++  , ("foldl'"     , {-# SCC "Prelude::foldl'" #-}+                    foldl'V sym)++  , ("deepseq"    , {-# SCC "Prelude::deepseq" #-}+                    PTyPoly \_a ->+                    PTyPoly \_b ->+                    PFun \x ->+                    PFun \y ->+                    PPrim do _ <- forceValue =<< x+                             y)++  , ("parmap"     , {-# SCC "Prelude::parmap" #-}+                    parmapV sym)++  , ("fromZ"      , {-# SCC "Prelude::fromZ" #-}+                    fromZV sym)++  ]
+ src/Cryptol/Eval/Prims.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE LambdaCase #-}+module Cryptol.Eval.Prims where++import Cryptol.Backend+import Cryptol.Eval.Type+import Cryptol.Eval.Value+import Cryptol.ModuleSystem.Name+import Cryptol.TypeCheck.Solver.InfNat(Nat'(..))+import Cryptol.Utils.Panic++-- | This type provides a lightweight syntactic framework for defining+--   Cryptol primitives.  The main purpose of this type is to provide+--   an abstraction barrier that insulates the definitions of primitives+--   from possible changes in the representation of values.+data Prim sym+  = PFun (SEval sym (GenValue sym) -> Prim sym)+  | PStrict (GenValue sym -> Prim sym)+  | PWordFun (SWord sym -> Prim sym)+  | PFloatFun (SFloat sym -> Prim sym)+  | PTyPoly (TValue -> Prim sym)+  | PNumPoly (Nat' -> Prim sym)+  | PFinPoly (Integer -> Prim sym)+  | PPrim (SEval sym (GenValue sym))+  | PVal (GenValue sym)++-- | Evaluate a primitive into a value computation+evalPrim :: Backend sym => sym -> Name -> Prim sym -> SEval sym (GenValue sym)+evalPrim sym nm p = case p of+  PFun f      -> lam sym (evalPrim sym nm . f)+  PStrict f   -> lam sym (\x -> evalPrim sym nm . f =<< x)+  PWordFun f  -> lam sym (\x -> evalPrim sym nm . f =<< (fromVWord sym (show nm) =<< x))+  PFloatFun f -> flam sym (evalPrim sym nm . f)+  PTyPoly f   -> tlam sym (evalPrim sym nm . f)+  PNumPoly f  -> nlam sym (evalPrim sym nm . f)+  PFinPoly f  -> nlam sym (\case Inf -> panic "PFin" ["Unexpected `inf`", show nm];+                                 Nat n -> evalPrim sym nm (f n))+  PPrim m     -> m+  PVal v      -> pure v
src/Cryptol/Eval/Reference.lhs view
@@ -28,7 +28,6 @@ > import Data.Ord (comparing) > import Data.Map (Map) > import qualified Data.Map as Map-> import qualified Data.IntMap as IntMap > import qualified Data.Text as T (pack) > import LibBF (BigFloat) > import qualified LibBF as FP@@ -39,8 +38,9 @@ > import Cryptol.TypeCheck.AST > import Cryptol.Backend.FloatHelpers (BF(..)) > import qualified Cryptol.Backend.FloatHelpers as FP-> import Cryptol.Backend.Monad (EvalError(..), PPOpts(..))-> import Cryptol.Eval.Type (TValue(..), isTBit, evalValType, evalNumType, TypeEnv)+> import Cryptol.Backend.Monad (EvalError(..))+> import Cryptol.Eval.Type+>   (TValue(..), isTBit, evalValType, evalNumType, TypeEnv, bindTypeVar) > import Cryptol.Eval.Concrete (mkBv, ppBV, lg2) > import Cryptol.Utils.Ident (Ident,PrimIdent, prelPrim, floatPrim) > import Cryptol.Utils.Panic (panic)@@ -48,7 +48,7 @@ > import Cryptol.Utils.RecordMap > > import qualified Cryptol.ModuleSystem as M-> import qualified Cryptol.ModuleSystem.Env as M (loadedModules)+> import qualified Cryptol.ModuleSystem.Env as M (loadedModules,loadedNewtypes)  Overview ========@@ -250,14 +250,14 @@ > > instance Semigroup Env where >   l <> r = Env->     { envVars  = Map.union (envVars  l) (envVars  r)->     , envTypes = IntMap.union (envTypes l) (envTypes r)+>     { envVars  = envVars  l <> envVars  r+>     , envTypes = envTypes l <> envTypes r  >     } > > instance Monoid Env where >   mempty = Env->     { envVars  = Map.empty->     , envTypes = IntMap.empty+>     { envVars  = mempty+>     , envTypes = mempty >     } >   mappend l r = l <> r >@@ -267,7 +267,7 @@ > > -- | Bind a type variable of kind # or *. > bindType :: TVar -> Either Nat' TValue -> Env -> Env-> bindType p ty env = env { envTypes = IntMap.insert (tvUnique p) ty (envTypes env) }+> bindType p ty env = env { envTypes = bindTypeVar p ty (envTypes env) }   Evaluation@@ -284,6 +284,8 @@ > evalExpr env expr = >   case expr of >+>     ELocated _ e -> evalExpr env e+> >     EList es _ty  -> >       pure $ VList (Nat (genericLength es)) [ evalExpr env e | e <- es ] >@@ -340,13 +342,15 @@ ---------  Apply the the given selector form to the given value.+Note that record selectors work uniformly on both record+types and on newtypes.  > evalSel :: Selector -> Value -> E Value > evalSel sel val = >   case sel of >     TupleSel n _  -> tupleSel n val >     RecordSel n _ -> recordSel n val->     ListSel n _  -> listSel n val+>     ListSel n _   -> listSel n val >   where >     tupleSel n v = >       case v of@@ -366,12 +370,15 @@   Update the given value using the given selector and new value.+Note that record selectors work uniformly on both record+types and on newtypes.  > evalSet :: TValue -> E Value -> Selector -> E Value -> E Value > evalSet tyv val sel fval = >   case (tyv, sel) of >     (TVTuple ts, TupleSel n _) -> updTupleAt ts n >     (TVRec fs, RecordSel n _)  -> updRecAt fs n+>     (TVNewtype _ _ fs, RecordSel n _) -> updRecAt fs n >     (TVSeq len _, ListSel n _) -> updSeqAt len n >     (_, _) -> evalPanic "evalSet" ["type/selector mismatch", show tyv, show sel] >   where@@ -463,7 +470,8 @@ >          -> Expr        -- ^ Head expression of the comprehension >          -> [[Match]]   -- ^ List of parallel comprehension branches >          -> E Value-> evalComp env expr branches = pure $ VList len [ evalExpr e expr | e <- envs ]+> evalComp env expr branches =+>     pure $ VList len [ evalExpr e expr | e <- envs ] >   where >     -- Generate a new environment for each iteration of each >     -- parallel branch.@@ -504,8 +512,27 @@ >   case dDefinition d of >     DPrim   -> (dName d, pure (evalPrim (dName d))) >     DExpr e -> (dName d, evalExpr env e)+> +Newtypes+-------- +At runtime, newtypes values are represented in exactly+the same way as records.  The constructor function for+newtypes is thus basically just an identity function+that consumes and ignores its type arguments.++> evalNewtypeDecl :: Env -> Newtype -> Env+> evalNewtypeDecl env nt = bindVar (ntName nt, pure val) env +>   where+>     val = foldr tabs con (ntParams nt)+>     con = VFun (\x -> x)+>     tabs tp body =+>       case tpKind tp of+>         KType -> VPoly (\_ -> pure body)+>         KNum  -> VNumPoly (\_ -> pure body)+>         k -> evalPanic "evalNewtypeDecl" ["illegal newtype parameter kind", show k]+ Primitives ========== @@ -909,7 +936,7 @@ >                               | (f, fty) <- canonicalFields fields ] > zero (TVFun _ bty)  = VFun (\_ -> pure (zero bty)) > zero (TVAbstract{}) = evalPanic "zero" ["Abstract type not in `Zero`"]-+> zero (TVNewtype{})  = evalPanic "zero" ["Newtype not in `Zero`"]  Literals --------@@ -978,6 +1005,7 @@ >         TVRational   -> evalPanic "logicUnary" ["Rational not in class Logic"] >         TVFloat{}    -> evalPanic "logicUnary" ["Float not in class Logic"] >         TVAbstract{} -> evalPanic "logicUnary" ["Abstract type not in `Logic`"]+>         TVNewtype{}  -> evalPanic "logicUnary" ["Newtype not in `Logic`"]  > logicBinary :: (Bool -> Bool -> Bool) -> TValue -> E Value -> E Value -> E Value > logicBinary op = go@@ -1016,6 +1044,7 @@ >         TVRational   -> evalPanic "logicBinary" ["Rational not in class Logic"] >         TVFloat{}    -> evalPanic "logicBinary" ["Float not in class Logic"] >         TVAbstract{} -> evalPanic "logicBinary" ["Abstract type not in `Logic`"]+>         TVNewtype{}  -> evalPanic "logicBinary" ["Newtype not in `Logic`"]   Ring Arithmetic@@ -1063,6 +1092,8 @@ >           pure $ VRecord [ (f, go fty) | (f, fty) <- canonicalFields fs ] >         TVAbstract {} -> >           evalPanic "arithNullary" ["Abstract type not in `Ring`"]+>         TVNewtype {} ->+>           evalPanic "arithNullary" ["Newtype type not in `Ring`"]  > ringUnary :: >   (Integer -> E Integer) ->@@ -1101,6 +1132,8 @@ >                             | (f, fty) <- canonicalFields fs ] >         TVAbstract {} -> >           evalPanic "arithUnary" ["Abstract type not in `Ring`"]+>         TVNewtype {} ->+>           evalPanic "arithUnary" ["Newtype not in `Ring`"]  > ringBinary :: >   (Integer -> Integer -> E Integer) ->@@ -1149,6 +1182,8 @@ >                | (f, fty) <- canonicalFields fs ] >         TVAbstract {} -> >           evalPanic "arithBinary" ["Abstract type not in class `Ring`"]+>         TVNewtype {} ->+>           evalPanic "arithBinary" ["Newtype not in class `Ring`"]   Integral@@ -1325,6 +1360,8 @@ >          lexList (zipWith3 lexCompare tys ls rs) >     TVAbstract {} -> >       evalPanic "lexCompare" ["Abstract type not in `Cmp`"]+>     TVNewtype {} ->+>       evalPanic "lexCompare" ["Newtype not in `Cmp`"] > > lexList :: [E Ordering] -> E Ordering > lexList [] = pure EQ@@ -1379,6 +1416,8 @@ >          lexList (zipWith3 lexSignedCompare tys ls rs) >     TVAbstract {} -> >       evalPanic "lexSignedCompare" ["Abstract type not in `Cmp`"]+>     TVNewtype {} ->+>       evalPanic "lexSignedCompare" ["Newtype type not in `Cmp`"]   Sequences@@ -1690,7 +1729,10 @@ running the reference evaluator on an expression.  > evaluate :: Expr -> M.ModuleCmd (E Value)-> evaluate expr (_, _, modEnv) = return (Right (evalExpr env expr, modEnv), [])+> evaluate expr minp = return (Right (val, modEnv), []) >   where+>     modEnv = M.minpModuleEnv minp >     extDgs = concatMap mDecls (M.loadedModules modEnv)->     env = foldl evalDeclGroup mempty extDgs+>     nts    = Map.elems (M.loadedNewtypes modEnv)+>     env    = foldl evalDeclGroup (foldl evalNewtypeDecl mempty nts) extDgs+>     val    = evalExpr env expr
src/Cryptol/Eval/SBV.hs view
@@ -6,6 +6,7 @@ -- Stability   :  provisional -- Portability :  portable +{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -21,7 +22,6 @@   ) where  import qualified Control.Exception as X-import           Control.Monad (join) import           Control.Monad.IO.Class (MonadIO(..)) import           Data.Bits (bit, shiftL) import qualified Data.Map as Map@@ -33,8 +33,9 @@ import Cryptol.Backend.Monad ( EvalError(..), Unsupported(..) ) import Cryptol.Backend.SBV -import Cryptol.Eval.Type (TValue(..), finNat')+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.Utils.Ident@@ -46,106 +47,12 @@ -- Primitives ------------------------------------------------------------------  -- See also Cryptol.Eval.Concrete.primTable-primTable :: SBV -> Map.Map PrimIdent Value-primTable sym =+primTable :: SBV -> IO EvalOpts -> Map.Map PrimIdent (Prim SBV)+primTable sym getEOpts =+  Map.union (genericPrimTable sym getEOpts) $   Map.fromList $ map (\(n, v) -> (prelPrim (T.pack n), v)) -  [ -- Literals-    ("True"        , VBit (bitLit sym True))-  , ("False"       , VBit (bitLit sym False))-  , ("number"      , ecNumberV sym) -- Converts a numeric type into its corresponding value.-                                    -- { val, rep } (Literal val rep) => rep-  , ("fraction"     , ecFractionV sym)-  , ("ratio"       , ratioV sym)--    -- Zero-  , ("zero"        , VPoly (zeroV sym))--    -- Logic-  , ("&&"          , binary (andV sym))-  , ("||"          , binary (orV sym))-  , ("^"           , binary (xorV sym))-  , ("complement"  , unary  (complementV sym))--    -- Ring-  , ("fromInteger" , fromIntegerV sym)-  , ("+"           , binary (addV sym))-  , ("-"           , binary (subV sym))-  , ("negate"      , unary (negateV sym))-  , ("*"           , binary (mulV sym))--    -- Integral-  , ("toInteger"   , toIntegerV sym)-  , ("/"           , binary (divV sym))-  , ("%"           , binary (modV sym))-  , ("^^"          , expV sym)-  , ("infFrom"     , infFromV sym)-  , ("infFromThen" , infFromThenV sym)--    -- Field-  , ("recip"       , recipV sym)-  , ("/."          , fieldDivideV sym)--    -- Round-  , ("floor"       , unary (floorV sym))-  , ("ceiling"     , unary (ceilingV sym))-  , ("trunc"       , unary (truncV sym))-  , ("roundAway"   , unary (roundAwayV sym))-  , ("roundToEven" , unary (roundToEvenV sym))--    -- Word operations-  , ("/$"          , sdivV sym)-  , ("%$"          , smodV sym)-  , ("lg2"         , lg2V sym)-  , (">>$"         , sshrV sym)--    -- Cmp-  , ("<"           , binary (lessThanV sym))-  , (">"           , binary (greaterThanV sym))-  , ("<="          , binary (lessThanEqV sym))-  , (">="          , binary (greaterThanEqV sym))-  , ("=="          , binary (eqV sym))-  , ("!="          , binary (distinctV sym))--    -- SignedCmp-  , ("<$"          , binary (signedLessThanV sym))--    -- Finite enumerations-  , ("fromTo"      , fromToV sym)-  , ("fromThenTo"  , fromThenToV sym)--    -- Sequence manipulations-  , ("#"          , -- {a,b,d} (fin a) => [a] d -> [b] d -> [a + b] d-     nlam $ \ front ->-     nlam $ \ back  ->-     tlam $ \ elty  ->-     lam  $ \ l     -> return $-     lam  $ \ r     -> join (ccatV sym front back elty <$> l <*> r))--  , ("join"       ,-     nlam $ \ parts ->-     nlam $ \ (finNat' -> each)  ->-     tlam $ \ a     ->-     lam  $ \ x     ->-       joinV sym parts each a =<< x)--  , ("split"       , ecSplitV sym)--  , ("splitAt"    ,-     nlam $ \ front ->-     nlam $ \ back  ->-     tlam $ \ a     ->-     lam  $ \ x     ->-       splitAtV sym front back a =<< x)--  , ("reverse"    , nlam $ \_a ->-                    tlam $ \_b ->-                     lam $ \xs -> reverseV sym =<< xs)--  , ("transpose"  , nlam $ \a ->-                    nlam $ \b ->-                    tlam $ \c ->-                     lam $ \xs -> transposeV sym a b c =<< xs)+  [ (">>$"         , sshrV sym)      -- Shifts and rotates   , ("<<"          , logicShift sym "<<"@@ -179,52 +86,8 @@   , ("update"      , updatePrim sym (updateFrontSym_word sym) (updateFrontSym sym))   , ("updateEnd"   , updatePrim sym (updateBackSym_word sym) (updateBackSym sym)) -    -- Misc--  , ("fromZ"       , fromZV sym)--  , ("foldl"       , foldlV sym)-  , ("foldl'"      , foldl'V sym)--  , ("deepseq"     ,-      tlam $ \_a ->-      tlam $ \_b ->-       lam $ \x -> pure $-       lam $ \y ->-         do _ <- forceValue =<< x-            y)--  , ("parmap"      , parmapV sym)--    -- {at,len} (fin len) => [len][8] -> at-  , ("error"       ,-      tlam $ \a ->-      nlam $ \_ ->-      VFun $ \s -> errorV sym a =<< (valueToString sym =<< s))--  , ("random"      ,-      tlam $ \a ->-      wlam sym $ \x ->-         case integerAsLit sym x of-           Just i  -> randomV sym a i-           Nothing -> cryUserError sym "cannot evaluate 'random' with symbolic inputs")--     -- The trace function simply forces its first two-     -- values before returing the third in the symbolic-     -- evaluator.-  , ("trace",-      nlam $ \_n ->-      tlam $ \_a ->-      tlam $ \_b ->-       lam $ \s -> return $-       lam $ \x -> return $-       lam $ \y -> do-         _ <- s-         _ <- x-         y)   ] - indexFront ::   SBV ->   Nat' ->@@ -468,13 +331,14 @@        go f (WordVal x :vs) = go (f . (x:)) vs        go _f (LargeBitsVal _ _ : _) = Nothing -sshrV :: SBV -> Value+sshrV :: SBV -> Prim SBV sshrV sym =-  nlam $ \n ->-  tlam $ \ix ->-  wlam sym $ \x -> return $-  lam $ \y ->-   y >>= asIndex sym ">>$" ix >>= \case+  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)
src/Cryptol/Eval/Type.hs view
@@ -11,7 +11,7 @@ {-# LANGUAGE DeriveGeneric #-} module Cryptol.Eval.Type where -import Cryptol.Backend.Monad (evalPanic, typeCannotBeDemoted)+import Cryptol.Backend.Monad (evalPanic) import Cryptol.TypeCheck.AST import Cryptol.TypeCheck.PP(pp) import Cryptol.TypeCheck.Solver.InfNat@@ -38,8 +38,11 @@   | TVTuple [TValue]          -- ^ @ (a, b, c )@   | TVRec (RecordMap Ident TValue) -- ^ @ { x : a, y : b, z : c } @   | TVFun TValue TValue       -- ^ @ a -> b @+  | TVNewtype Newtype+              [Either Nat' TValue]+              (RecordMap Ident TValue)     -- ^ a named newtype   | TVAbstract UserTC [Either Nat' TValue] -- ^ an abstract type-    deriving (Generic, NFData)+    deriving (Generic, NFData, Eq)  -- | Convert a type value back into a regular type tValTy :: TValue -> Type@@ -56,13 +59,17 @@     TVTuple ts  -> tTuple (map tValTy ts)     TVRec fs    -> tRec (fmap tValTy fs)     TVFun t1 t2 -> tFun (tValTy t1) (tValTy t2)-    TVAbstract u vs -> tAbstract u (map arg vs)-      where arg x = case x of-                      Left Inf     -> tInf-                      Left (Nat n) -> tNum n-                      Right v      -> tValTy v+    TVNewtype nt vs _ -> tNewtype nt (map tNumValTy vs)+    TVAbstract u vs -> tAbstract u (map tNumValTy vs) +tNumTy :: Nat' -> Type+tNumTy Inf     = tInf+tNumTy (Nat n) = tNum n +tNumValTy :: Either Nat' TValue -> Type+tNumValTy = either tNumTy tValTy++ instance Show TValue where   showsPrec p v = showsPrec p (tValTy v) @@ -90,20 +97,38 @@  -- Type Evaluation ------------------------------------------------------------- -type TypeEnv = IntMap.IntMap (Either Nat' TValue)+newtype TypeEnv =+  TypeEnv+  { envTypeMap  :: IntMap.IntMap (Either Nat' TValue) } +instance Monoid TypeEnv where+  mempty = TypeEnv mempty +instance Semigroup TypeEnv where+  l <> r = TypeEnv+    { envTypeMap  = IntMap.union (envTypeMap l) (envTypeMap r) }++lookupTypeVar :: TVar -> TypeEnv -> Maybe (Either Nat' TValue)+lookupTypeVar tv env = IntMap.lookup (tvUnique tv) (envTypeMap env)++bindTypeVar :: TVar -> Either Nat' TValue -> TypeEnv -> TypeEnv+bindTypeVar tv ty env = env{ envTypeMap = IntMap.insert (tvUnique tv) ty (envTypeMap env) }+ -- | Evaluation for types (kind * or #). evalType :: TypeEnv -> Type -> Either Nat' TValue evalType env ty =   case ty of     TVar tv ->-      case IntMap.lookup (tvUnique tv) env of+      case lookupTypeVar tv env of         Just v -> v         Nothing -> evalPanic "evalType" ["type variable not bound", show tv]      TUser _ _ ty'  -> evalType env ty'     TRec fields    -> Right $ TVRec (fmap val fields)++    TNewtype nt ts -> Right $ TVNewtype nt tvs $ evalNewtypeBody env nt tvs+        where tvs = map (evalType env) ts+     TCon (TC c) ts ->       case (c, ts) of         (TCBit, [])     -> Right $ TVBit@@ -128,7 +153,6 @@                 , "*** Name: " ++ show (pp u)                 ] -        -- FIXME: What about TCNewtype?         _ -> evalPanic "evalType" ["not a value type", show ty]     TCon (TF f) ts      -> Left $ evalTF f (map num ts)     TCon (PC p) _       -> evalPanic "evalType" ["invalid predicate symbol", show p]@@ -142,6 +166,16 @@                Inf   -> evalPanic "evalType"                                   ["Expecting a finite size, but got `inf`"] +-- | Evaluate the body of a newtype, given evaluated arguments+evalNewtypeBody :: TypeEnv -> Newtype -> [Either Nat' TValue] -> RecordMap Ident TValue+evalNewtypeBody env0 nt args = fmap (evalValType env') (ntFields nt)+  where+  env' = loop env0 (ntParams nt) args++  loop env [] [] = env+  loop env (p:ps) (a:as) = loop (bindTypeVar (TVBound p) a env) ps as+  loop _ _ _ = evalPanic "evalNewtype" ["type parameter/argument mismatch"]+ -- | Evaluation for value types (kind *). evalValType :: TypeEnv -> Type -> TValue evalValType env ty =@@ -175,5 +209,5 @@   | otherwise  = evalPanic "evalTF"                         ["Unexpected type function:", show ty] -  where mb = fromMaybe (typeCannotBeDemoted ty)+  where mb = fromMaybe (evalPanic "evalTF" ["type cannot be demoted", show (pp ty)])         ty = TCon (TF f) (map tNat' vs)
src/Cryptol/Eval/Value.hs view
@@ -30,10 +30,11 @@   , forceValue   , Backend(..)   , asciiMode++  , EvalOpts(..)     -- ** Value introduction operations   , word   , lam-  , wlam   , flam   , tlam   , nlam@@ -95,16 +96,21 @@ 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 qualified Cryptol.Backend.Arch as Arch-import Cryptol.Backend.Monad ( PPOpts(..), evalPanic, wordTooWide, defaultPPOpts, asciiMode )+import Cryptol.Backend.Monad+  ( evalPanic, wordTooWide, CallStack, combineCallStacks )+import Cryptol.Backend.FloatHelpers (fpPP) 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@@ -113,6 +119,12 @@  import GHC.Generics (Generic) +-- | Some options for evalutaion+data EvalOpts = EvalOpts+  { evalLogger :: Logger    -- ^ Where to print stuff (e.g., for @trace@)+  , evalPPOpts :: PPOpts    -- ^ How to pretty print things.+  }+ -- Values ----------------------------------------------------------------------  -- | A sequence map represents a mapping from nonnegative integer indices@@ -135,22 +147,22 @@ largeBitSize = 1 `shiftL` 48  -- | Generate a finite sequence map from a list of values-finiteSeqMap :: Backend sym => sym -> [SEval sym (GenValue sym)] -> SeqMap sym-finiteSeqMap sym xs =+finiteSeqMap :: [SEval sym (GenValue sym)] -> SeqMap sym+finiteSeqMap xs =    UpdateSeqMap       (Map.fromList (zip [0..] xs))-      (invalidIndex sym)+      (\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 => [SEval sym (GenValue sym)] -> SEval sym (SeqMap sym)-infiniteSeqMap xs =+infiniteSeqMap :: Backend sym => sym -> [SEval sym (GenValue sym)] -> SEval sym (SeqMap sym)+infiniteSeqMap sym xs =    -- TODO: use an int-trie?-   memoMap (IndexSeqMap $ \i -> genericIndex xs i)+   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] ]+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)]@@ -191,17 +203,18 @@  -- | Given a sequence map, return a new sequence map that is memoized using --   a finite map memo table.-memoMap :: (MonadIO m, Backend sym) => SeqMap sym -> m (SeqMap sym)-memoMap x = do+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)+  return $ IndexSeqMap (memo cache stk)    where-  memo cache i = do+  memo cache stk i = do     mz <- liftIO (Map.lookup i <$> readIORef cache)     case mz of       Just z  -> return z-      Nothing -> doEval cache i+      Nothing -> sWithCallStack sym stk (doEval cache i)    doEval cache i = do     v <- lookupSeqMap x i@@ -212,20 +225,22 @@ --   sequence maps. zipSeqMap ::   Backend sym =>+  sym ->   (GenValue sym -> GenValue sym -> SEval sym (GenValue sym)) ->   SeqMap sym ->   SeqMap sym ->   SEval sym (SeqMap sym)-zipSeqMap f x y =-  memoMap (IndexSeqMap $ \i -> join (f <$> lookupSeqMap x i <*> lookupSeqMap y i))+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 f x =-  memoMap (IndexSeqMap $ \i -> f =<< lookupSeqMap x i)+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@@ -280,7 +295,8 @@  -- | 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 :: 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)@@ -308,9 +324,9 @@                                                --   Invariant: VSeq is never a sequence of bits   | VWord !Integer !(SEval sym (WordValue sym))  -- ^ @ [n]Bit @   | VStream !(SeqMap sym)                   -- ^ @ [inf]a @-  | VFun (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -- ^ functions-  | VPoly (TValue -> SEval sym (GenValue sym))   -- ^ polymorphic values (kind *)-  | VNumPoly (Nat' -> SEval sym (GenValue sym))  -- ^ polymorphic values (kind #)+  | 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  @@ -331,9 +347,9 @@   VFloat f    -> seq f (return ())   VWord _ wv  -> forceWordValue =<< wv   VStream _   -> return ()-  VFun _      -> return ()-  VPoly _     -> return ()-  VNumPoly _  -> return ()+  VFun{}      -> return ()+  VPoly{}     -> return ()+  VNumPoly{}  -> return ()   @@ -348,9 +364,9 @@     VSeq n _   -> "seq:" ++ show n     VWord n _  -> "word:"  ++ show n     VStream _  -> "stream"-    VFun _     -> "fun"-    VPoly _    -> "poly"-    VNumPoly _ -> "numpoly"+    VFun{}     -> "fun"+    VPoly{}    -> "poly"+    VNumPoly{} -> "numpoly"   -- Pretty Printing -------------------------------------------------------------@@ -371,10 +387,10 @@       ppField (f,r) = pp f <+> char '=' <+> r     VTuple vals        -> do vals' <- traverse (>>=loop) vals                              return $ parens (sep (punctuate comma vals'))-    VBit b             -> return $ ppBit x b-    VInteger i         -> return $ ppInteger x opts i-    VRational q        -> return $ ppRational x opts q-    VFloat i           -> return $ ppFloat x opts i+    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     VStream vals       -> do vals' <- traverse (>>=loop) $ enumerateSeqMap (useInfLength opts) vals@@ -382,12 +398,12 @@                                    $ punctuate comma                                    ( vals' ++ [text "..."]                                    )-    VFun _             -> return $ text "<function>"-    VPoly _            -> return $ text "<polymorphic value>"-    VNumPoly _         -> return $ text "<polymorphic value>"+    VFun{}             -> return $ text "<function>"+    VPoly{}            -> return $ text "<polymorphic value>"+    VNumPoly{}         -> return $ text "<polymorphic value>"    ppWordVal :: WordValue sym -> SEval sym Doc-  ppWordVal w = ppWord x opts <$> asWordVal x w+  ppWordVal w = ppSWord x opts =<< asWordVal x w    ppWordSeq :: Integer -> SeqMap sym -> SEval sym Doc   ppWordSeq sz vals = do@@ -399,11 +415,102 @@         -> do vs <- traverse (fromVWord x "ppWordSeq") ws               case traverse (wordAsChar x) vs of                 Just str -> return $ text (show str)-                _ -> return $ brackets (fsep (punctuate comma $ map (ppWord x opts) vs))+                _ -> do vs' <- mapM (ppSWord x opts) vs+                        return $ brackets (fsep (punctuate comma vs'))       _ -> do ws' <- traverse loop ws               return $ brackets (fsep (punctuate comma ws')) +ppSBit :: Backend sym => sym -> SBit sym -> SEval sym Doc+ppSBit sym b =+  case bitAsLit sym b of+    Just True  -> pure (text "True")+    Just False -> pure (text "False")+    Nothing    -> pure (text "?") +ppSInteger :: Backend sym => sym -> SInteger sym -> SEval sym Doc+ppSInteger sym x =+  case integerAsLit sym x of+    Just i  -> pure (integer i)+    Nothing -> pure (text "[?]")++ppSFloat :: Backend sym => sym -> PPOpts -> SFloat sym -> SEval sym Doc+ppSFloat sym opts x =+  case fpAsLit sym x of+    Just fp -> pure (fpPP opts fp)+    Nothing -> pure (text "[?]")++ppSRational :: Backend sym => sym -> SRational sym -> SEval sym Doc+ppSRational sym (SRational n d)+  | Just ni <- integerAsLit sym n+  , Just di <- integerAsLit sym d+  = let q = ni % di in+      pure (text "(ratio" <+> integer (numerator q) <+> (integer (denominator q) <> text ")"))++  | otherwise+  = do n' <- ppSInteger sym n+       d' <- ppSInteger sym d+       pure (text "(ratio" <+> n' <+> (d' <> text ")"))++ppSWord :: Backend sym => sym -> PPOpts -> SWord sym -> SEval sym Doc+ppSWord sym opts bv+  | asciiMode opts width =+      case wordAsLit sym bv of+        Just (_,i) -> pure (text (show (toEnum (fromInteger i) :: Char)))+        Nothing    -> pure (text "?")++  | otherwise =+      case wordAsLit sym bv of+        Just (_,i) ->+          let val = value i in+          pure (prefix (length val) <.> text val)+        Nothing+          | base == 2  -> sliceDigits 1 "0b"+          | base == 8  -> sliceDigits 3 "0o"+          | base == 16 -> sliceDigits 4 "0x"+          | otherwise  -> pure (text "[?]")++  where+  width = wordLen sym bv++  base = if useBase opts > 36 then 10 else useBase opts++  padding bitsPerDigit len = text (replicate padLen '0')+    where+    padLen | m > 0     = d + 1+           | otherwise = d++    (d,m) = (fromInteger width - (len * bitsPerDigit))+                   `divMod` bitsPerDigit++  prefix len = case base of+    2  -> text "0b" <.> padding 1 len+    8  -> text "0o" <.> padding 3 len+    10 -> empty+    16 -> text "0x" <.> padding 4 len+    _  -> text "0"  <.> char '<' <.> int base <.> char '>'++  value i = showIntAtBase (toInteger base) (digits !!) i ""+  digits  = "0123456789abcdefghijklmnopqrstuvwxyz"++  toDigit w =+    case wordAsLit sym w of+      Just (_,i) | i <= 36 -> digits !! fromInteger i+      _ -> '?'++  sliceDigits bits pfx =+    do ws <- goDigits bits [] bv+       let ds = map toDigit ws+       pure (text pfx <.> text ds)++  goDigits bits ds w+    | wordLen sym w > bits =+        do (hi,lo) <- splitWord sym (wordLen sym w - bits) bits w+           goDigits bits (lo:ds) hi++    | wordLen sym w > 0 = pure (w:ds)++    | otherwise          = pure ds+ -- Value Constructors ----------------------------------------------------------  -- | Create a packed word of n bits.@@ -413,45 +520,41 @@   | otherwise                = VWord n (WordVal <$> wordLit sym n i)  -lam :: (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -> GenValue sym-lam  = VFun---- | Functions that assume word inputs-wlam :: Backend sym => sym -> (SWord sym -> SEval sym (GenValue sym)) -> GenValue sym-wlam sym f = VFun (\arg -> arg >>= fromVWord sym "wlam" >>= f)+-- | Construct a function value+lam :: Backend sym => sym -> (SEval sym (GenValue sym) -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)+lam sym f = VFun <$> sGetCallStack sym <*> pure f  -- | Functions that assume floating point inputs-flam :: Backend sym =>-        (SFloat sym -> SEval sym (GenValue sym)) -> GenValue sym-flam f = VFun (\arg -> arg >>= f . fromVFloat)--+flam :: Backend sym => sym ->+        (SFloat sym -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)+flam sym f = VFun <$> sGetCallStack sym <*> pure (\arg -> arg >>= f . fromVFloat)  -- | A type lambda that expects a 'Type'.-tlam :: Backend sym => (TValue -> GenValue sym) -> GenValue sym-tlam f = VPoly (return . f)+tlam :: Backend sym => sym -> (TValue -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)+tlam sym f = VPoly <$> sGetCallStack sym <*> pure f  -- | A type lambda that expects a 'Type' of kind #.-nlam :: Backend sym => (Nat' -> GenValue sym) -> GenValue sym-nlam f = VNumPoly (return . f)+nlam :: Backend sym => sym -> (Nat' -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)+nlam sym f = VNumPoly <$> sGetCallStack sym <*> pure f  -- | A type lambda that expects a finite numeric type.-ilam :: Backend sym => (Integer -> GenValue sym) -> GenValue sym-ilam f = nlam (\n -> case n of-                       Nat i -> f i-                       Inf   -> panic "ilam" [ "Unexpected `inf`" ])+ilam :: Backend sym => sym -> (Integer -> SEval sym (GenValue sym)) -> SEval sym (GenValue sym)+ilam sym f =+   nlam sym (\n -> case n of+                     Nat i -> f i+                     Inf   -> panic "ilam" [ "Unexpected `inf`" ])  -- | Generate a stream.-toStream :: Backend sym => [GenValue sym] -> SEval sym (GenValue sym)-toStream vs =-   VStream <$> infiniteSeqMap (map pure vs)+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 sym (map pure 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.@@ -460,7 +563,7 @@   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 vals+  Inf   -> toStream sym vals   -- | Construct either a finite sequence, or a stream.  In the finite case,@@ -537,22 +640,25 @@   go _ (_ : _) = Nothing  -- | Extract a function from a value.-fromVFun :: GenValue sym -> (SEval sym (GenValue sym) -> SEval sym (GenValue sym))-fromVFun val = case val of-  VFun f -> f-  _      -> evalPanic "fromVFun" ["not a function"]+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"]  -- | Extract a polymorphic function from a value.-fromVPoly :: GenValue sym -> (TValue -> SEval sym (GenValue sym))-fromVPoly val = case val of-  VPoly f -> f-  _       -> evalPanic "fromVPoly" ["not a polymorphic 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"]  -- | Extract a polymorphic function from a value.-fromVNumPoly :: GenValue sym -> (Nat' -> SEval sym (GenValue sym))-fromVNumPoly val = case val of-  VNumPoly f -> f-  _          -> evalPanic "fromVNumPoly" ["not a polymorphic 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"]  -- | Extract a tuple from a value. fromVTuple :: GenValue sym -> [SEval sym (GenValue sym)]
src/Cryptol/Eval/What4.hs view
@@ -18,22 +18,20 @@ module Cryptol.Eval.What4   ( Value   , primTable-  , floatPrims   ) where  import qualified Control.Exception as X import           Control.Concurrent.MVar-import           Control.Monad (join,foldM)+import           Control.Monad (foldM) import           Control.Monad.IO.Class import           Data.Bits import qualified Data.Map as Map-import           Data.Map (Map) import qualified Data.Set as Set import           Data.Text (Text) import qualified Data.Text as Text import           Data.Parameterized.Context-import           Data.Parameterized.Some import           Data.Parameterized.TraversableFC+import           Data.Parameterized.Some import qualified Data.BitVector.Sized as BV  import qualified What4.Interface as W4@@ -43,10 +41,10 @@ import Cryptol.Backend import Cryptol.Backend.Monad ( EvalError(..), Unsupported(..) ) import Cryptol.Backend.What4-import qualified Cryptol.Backend.What4.SFloat as W4  import Cryptol.Eval.Generic-import Cryptol.Eval.Type (finNat', TValue(..))+import Cryptol.Eval.Prims+import Cryptol.Eval.Type (TValue(..)) import Cryptol.Eval.Value  import qualified Cryptol.SHA as SHA@@ -60,111 +58,17 @@ type Value sym = GenValue (What4 sym)  -- See also Cryptol.Prims.Eval.primTable-primTable :: W4.IsSymExprBuilder sym => What4 sym -> Map.Map PrimIdent (Value sym)-primTable sym =+primTable :: W4.IsSymExprBuilder sym => What4 sym -> IO EvalOpts -> Map.Map PrimIdent (Prim (What4 sym))+primTable sym getEOpts =   let w4sym = w4 sym in-  Map.union (floatPrims sym) $   Map.union (suiteBPrims sym) $   Map.union (primeECPrims sym) $+  Map.union (genericFloatTable sym) $+  Map.union (genericPrimTable sym getEOpts) $    Map.fromList $ map (\(n, v) -> (prelPrim n, v)) -  [ -- Literals-    ("True"        , VBit (bitLit sym True))-  , ("False"       , VBit (bitLit sym False))-  , ("number"      , ecNumberV sym) -- Converts a numeric type into its corresponding value.-                                    -- { val, rep } (Literal val rep) => rep-  , ("fraction"    , ecFractionV sym)-  , ("ratio"       , ratioV sym)--    -- Zero-  , ("zero"        , VPoly (zeroV sym))--    -- Logic-  , ("&&"          , binary (andV sym))-  , ("||"          , binary (orV sym))-  , ("^"           , binary (xorV sym))-  , ("complement"  , unary  (complementV sym))--    -- Ring-  , ("fromInteger" , fromIntegerV sym)-  , ("+"           , binary (addV sym))-  , ("-"           , binary (subV sym))-  , ("negate"      , unary (negateV sym))-  , ("*"           , binary (mulV sym))--    -- Integral-  , ("toInteger"   , toIntegerV sym)-  , ("/"           , binary (divV sym))-  , ("%"           , binary (modV sym))-  , ("^^"          , expV sym)-  , ("infFrom"     , infFromV sym)-  , ("infFromThen" , infFromThenV sym)--    -- Field-  , ("recip"       , recipV sym)-  , ("/."          , fieldDivideV sym)--    -- Round-  , ("floor"       , unary (floorV sym))-  , ("ceiling"     , unary (ceilingV sym))-  , ("trunc"       , unary (truncV sym))-  , ("roundAway"   , unary (roundAwayV sym))-  , ("roundToEven" , unary (roundToEvenV sym))--    -- Word operations-  , ("/$"          , sdivV sym)-  , ("%$"          , smodV sym)-  , ("lg2"         , lg2V sym)-  , (">>$"         , sshrV sym)--    -- Cmp-  , ("<"           , binary (lessThanV sym))-  , (">"           , binary (greaterThanV sym))-  , ("<="          , binary (lessThanEqV sym))-  , (">="          , binary (greaterThanEqV sym))-  , ("=="          , binary (eqV sym))-  , ("!="          , binary (distinctV sym))--    -- SignedCmp-  , ("<$"          , binary (signedLessThanV sym))--    -- Finite enumerations-  , ("fromTo"      , fromToV sym)-  , ("fromThenTo"  , fromThenToV sym)--    -- Sequence manipulations-  , ("#"          , -- {a,b,d} (fin a) => [a] d -> [b] d -> [a + b] d-     nlam $ \ front ->-     nlam $ \ back  ->-     tlam $ \ elty  ->-     lam  $ \ l     -> return $-     lam  $ \ r     -> join (ccatV sym front back elty <$> l <*> r))--  , ("join"       ,-     nlam $ \ parts ->-     nlam $ \ (finNat' -> each)  ->-     tlam $ \ a     ->-     lam  $ \ x     ->-       joinV sym parts each a =<< x)--  , ("split"       , ecSplitV sym)--  , ("splitAt"    ,-     nlam $ \ front ->-     nlam $ \ back  ->-     tlam $ \ a     ->-     lam  $ \ x     ->-       splitAtV sym front back a =<< x)--  , ("reverse"    , nlam $ \_a ->-                    tlam $ \_b ->-                     lam $ \xs -> reverseV sym =<< xs)--  , ("transpose"  , nlam $ \a ->-                    nlam $ \b ->-                    tlam $ \c ->-                     lam $ \xs -> transposeV sym a b c =<< xs)+  [ (">>$"         , sshrV sym)      -- Shifts and rotates   , ("<<"          , logicShift sym "<<"  shiftShrink@@ -187,52 +91,9 @@   , ("update"      , updatePrim sym (updateFrontSym_word sym) (updateFrontSym sym))   , ("updateEnd"   , updatePrim sym (updateBackSym_word sym)  (updateBackSym sym)) -    -- Misc--  , ("foldl"       , foldlV sym)-  , ("foldl'"      , foldl'V sym)--  , ("deepseq"     ,-      tlam $ \_a ->-      tlam $ \_b ->-       lam $ \x -> pure $-       lam $ \y ->-         do _ <- forceValue =<< x-            y)--  , ("parmap"      , parmapV sym)--  , ("fromZ"       , fromZV sym)--    -- {at,len} (fin len) => [len][8] -> at-  , ("error"       ,-      tlam $ \a ->-      nlam $ \_ ->-      VFun $ \s -> errorV sym a =<< (valueToString sym =<< s))--  , ("random"      ,-      tlam $ \a ->-      wlam sym $ \x ->-         case wordAsLit sym x of-           Just (_,i)  -> randomV sym a i-           Nothing -> cryUserError sym "cannot evaluate 'random' with symbolic inputs")--     -- The trace function simply forces its first two-     -- values before returing the third in the symbolic-     -- evaluator.-  , ("trace",-      nlam $ \_n ->-      tlam $ \_a ->-      tlam $ \_b ->-       lam $ \s -> return $-       lam $ \x -> return $-       lam $ \y -> do-         _ <- s-         _ <- x-         y)   ] -primeECPrims :: W4.IsSymExprBuilder sym => What4 sym -> Map.Map PrimIdent (Value sym)+primeECPrims :: W4.IsSymExprBuilder sym => What4 sym -> Map.Map PrimIdent (Prim (What4 sym)) primeECPrims sym = Map.fromList $ [ (primeECPrim n, v) | (n,v) <- prims ]  where  (~>) = (,)@@ -240,8 +101,9 @@  prims =   [ -- {p} (prime p, p > 3) => ProjectivePoint p -> ProjectivePoint p     "ec_double" ~>-      ilam \p ->-       lam \s ->+      PFinPoly \p ->+      PFun     \s ->+      PPrim          do p' <- integerLit sym p             s' <- toProjectivePoint sym =<< s             addUninterpWarning sym "Prime ECC"@@ -252,9 +114,10 @@      -- {p} (prime p, p > 3) => ProjectivePoint p -> ProjectivePoint p -> ProjectivePoint p   , "ec_add_nonzero" ~>-      ilam \p ->-       lam \s -> pure $-       lam \t ->+      PFinPoly \p ->+      PFun     \s ->+      PFun     \t ->+      PPrim          do p' <- integerLit sym p             s' <- toProjectivePoint sym =<< s             t' <- toProjectivePoint sym =<< t@@ -266,9 +129,10 @@      -- {p} (prime p, p > 3) => Z p -> ProjectivePoint p -> ProjectivePoint p   , "ec_mult" ~>-      ilam \p ->-       lam \k -> pure $-       lam \s ->+      PFinPoly \p ->+      PFun     \k ->+      PFun     \s ->+      PPrim          do p' <- integerLit sym p             k' <- fromVInteger <$> k             s' <- toProjectivePoint sym =<< s@@ -280,11 +144,12 @@      -- {p} (prime p, p > 3) => Z p -> ProjectivePoint p -> Z p -> ProjectivePoint p -> ProjectivePoint p   , "ec_twin_mult" ~>-      ilam \p ->-       lam \j -> pure $-       lam \s -> pure $-       lam \k -> pure $-       lam \t ->+      PFinPoly \p ->+      PFun     \j ->+      PFun     \s ->+      PFun     \k ->+      PFun     \t ->+      PPrim          do p' <- integerLit sym p             j' <- fromVInteger <$> j             s' <- toProjectivePoint sym =<< s@@ -299,7 +164,6 @@             fromProjectivePoint sym z   ] - type ProjectivePoint = W4.BaseStructType (EmptyCtx ::> W4.BaseIntegerType ::> W4.BaseIntegerType ::> W4.BaseIntegerType)  projectivePointRepr :: W4.BaseTypeRepr ProjectivePoint@@ -321,37 +185,44 @@      z <- VInteger <$> W4.structField (w4 sym) p (natIndex @2)      pure $ VRecord $ recordFromFields [ (packIdent "x",pure x), (packIdent "y",pure y),(packIdent "z",pure z) ] -suiteBPrims :: W4.IsSymExprBuilder sym => What4 sym -> Map.Map PrimIdent (Value sym)++suiteBPrims :: W4.IsSymExprBuilder sym => What4 sym -> Map.Map PrimIdent (Prim (What4 sym)) suiteBPrims sym = Map.fromList $ [ (suiteBPrim n, v) | (n,v) <- prims ]  where  (~>) = (,)   prims =   [ "AESEncRound" ~>-       lam \st ->+       PFun \st ->+       PPrim          do addUninterpWarning sym "AES encryption"             applyAESStateFunc sym "AESEncRound" =<< st   , "AESEncFinalRound" ~>-       lam \st ->+       PFun \st ->+       PPrim          do addUninterpWarning sym "AES encryption"             applyAESStateFunc sym "AESEncFinalRound" =<< st   , "AESDecRound" ~>-       lam \st ->+       PFun \st ->+       PPrim          do addUninterpWarning sym "AES decryption"             applyAESStateFunc sym "AESDecRound" =<< st   , "AESDecFinalRound" ~>-       lam \st ->+       PFun \st ->+       PPrim          do addUninterpWarning sym "AES decryption"             applyAESStateFunc sym "AESDecFinalRound" =<< st   , "AESInvMixColumns" ~>-       lam \st ->+       PFun \st ->+       PPrim          do addUninterpWarning sym "AES key expansion"             applyAESStateFunc sym "AESInvMixColumns" =<< st      -- {k} (fin k, k >= 4, 8 >= k) => [k][32] -> [4*(k+7)][32]   , "AESKeyExpand" ~>-       ilam \k ->-        lam \st ->+       PFinPoly \k ->+       PFun     \st ->+       PPrim           do ss <- fromVSeq <$> st              -- pack the arguments into a k-tuple of 32-bit values              Some ws <- generateSomeM (fromInteger k) (\i -> Some <$> toWord32 sym "AESKeyExpand" ss (toInteger i))@@ -368,12 +239,13 @@                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)-                 _ -> invalidIndex sym i+                 _ -> evalPanic "AESKeyExpand" ["Index out of range", show k, show i]      -- {n} (fin n) => [n][16][32] -> [7][32]   , "processSHA2_224" ~>-    ilam \n ->-     lam \xs ->+    PFinPoly \n ->+    PFun     \xs ->+    PPrim        do blks <- enumerateSeqMap n . fromVSeq <$> xs           addUninterpWarning sym "SHA-224"           initSt <- liftIO (mkSHA256InitialState sym SHA.initialSHA224State)@@ -384,13 +256,14 @@                 do z <- liftIO $ W4.structField (w4 sym) finalSt idx                    case W4.testEquality (W4.exprType z) (W4.BaseBVRepr (W4.knownNat @32)) of                      Just W4.Refl -> fromWord32 z-                     Nothing -> invalidIndex sym i-              Nothing -> invalidIndex sym i+                     Nothing -> evalPanic "processSHA2_224" ["Index out of range", show i]+              Nothing -> evalPanic "processSHA2_224" ["Index out of range", show i]      -- {n} (fin n) => [n][16][32] -> [8][32]   , "processSHA2_256" ~>-    ilam \n ->-     lam \xs ->+    PFinPoly \n ->+    PFun     \xs ->+    PPrim        do blks <- enumerateSeqMap n . fromVSeq <$> xs           addUninterpWarning sym "SHA-256"           initSt <- liftIO (mkSHA256InitialState sym SHA.initialSHA256State)@@ -401,13 +274,14 @@                 do z <- liftIO $ W4.structField (w4 sym) finalSt idx                    case W4.testEquality (W4.exprType z) (W4.BaseBVRepr (W4.knownNat @32)) of                      Just W4.Refl -> fromWord32 z-                     Nothing -> invalidIndex sym i-              Nothing -> invalidIndex sym i+                     Nothing -> evalPanic "processSHA2_256" ["Index out of range", show i]+              Nothing -> evalPanic "processSHA2_256" ["Index out of range", show i]      -- {n} (fin n) => [n][16][64] -> [6][64]   , "processSHA2_384" ~>-    ilam \n ->-     lam \xs ->+    PFinPoly \n ->+    PFun     \xs ->+    PPrim        do blks <- enumerateSeqMap n . fromVSeq <$> xs           addUninterpWarning sym "SHA-384"           initSt <- liftIO (mkSHA512InitialState sym SHA.initialSHA384State)@@ -418,13 +292,14 @@                 do z <- liftIO $ W4.structField (w4 sym) finalSt idx                    case W4.testEquality (W4.exprType z) (W4.BaseBVRepr (W4.knownNat @64)) of                      Just W4.Refl -> fromWord64 z-                     Nothing -> invalidIndex sym i-              Nothing -> invalidIndex sym i+                     Nothing -> evalPanic "processSHA2_384" ["Index out of range", show i]+              Nothing -> evalPanic "processSHA2_384" ["Index out of range", show i]      -- {n} (fin n) => [n][16][64] -> [8][64]   , "processSHA2_512" ~>-    ilam \n ->-     lam \xs ->+    PFinPoly \n ->+    PFun     \xs ->+    PPrim        do blks <- enumerateSeqMap n . fromVSeq <$> xs           addUninterpWarning sym "SHA-512"           initSt <- liftIO (mkSHA512InitialState sym SHA.initialSHA512State)@@ -435,8 +310,8 @@                 do z <- liftIO $ W4.structField (w4 sym) finalSt idx                    case W4.testEquality (W4.exprType z) (W4.BaseBVRepr (W4.knownNat @64)) of                      Just W4.Refl -> fromWord64 z-                     Nothing -> invalidIndex sym i-              Nothing -> invalidIndex sym i+                     Nothing -> evalPanic "processSHA2_512" ["Index out of range", show i]+              Nothing -> evalPanic "processSHA2_512" ["Index out of range", show i]   ]  @@ -626,7 +501,7 @@           | i == 1 -> fromWord32 =<< liftIO (W4.structField (w4 sym) z (natIndex @1))           | i == 2 -> fromWord32 =<< liftIO (W4.structField (w4 sym) z (natIndex @2))           | i == 3 -> fromWord32 =<< liftIO (W4.structField (w4 sym) z (natIndex @3))-          | otherwise -> invalidIndex sym i+          | otherwise -> evalPanic "applyAESStateFunc" ["Index out of range", show funNm, show i]   where    nm = Text.unpack funNm@@ -636,13 +511,14 @@    argCtx = W4.knownRepr  -sshrV :: W4.IsSymExprBuilder sym => What4 sym -> Value sym+sshrV :: W4.IsSymExprBuilder sym => What4 sym -> Prim (What4 sym) sshrV sym =-  nlam $ \(Nat n) ->-  tlam $ \ix ->-  wlam sym $ \x -> return $-  lam $ \y ->-    y >>= asIndex sym ">>$" ix >>= \case+  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@@ -864,7 +740,7 @@     WordVal w | Just j <- SW.bvAsUnsignedInteger w ->       return $ updateSeqMap vs j val     _ ->-      memoMap $ IndexSeqMap $ \i ->+      memoMap sym $ IndexSeqMap $ \i ->       do b <- wordValueEqualsInteger sym wv i          iteValue sym b val (lookupSeqMap vs i) @@ -891,7 +767,7 @@     WordVal w | Just j <- SW.bvAsUnsignedInteger w ->       return $ updateSeqMap vs (n - 1 - j) val     _ ->-      memoMap $ IndexSeqMap $ \i ->+      memoMap sym $ IndexSeqMap $ \i ->       do b <- wordValueEqualsInteger sym wv (n - 1 - i)          iteValue sym b val (lookupSeqMap vs i) @@ -980,57 +856,3 @@      _ -> LargeBitsVal (wordValueSize sym wv) <$>            updateBackSym sym (Nat n) eltTy (asBitsMap sym bv) (Right wv) val------- | Table of floating point primitives-floatPrims :: W4.IsSymExprBuilder sym => What4 sym -> Map PrimIdent (Value sym)-floatPrims sym =-  Map.fromList [ (floatPrim i,v) | (i,v) <- nonInfixTable ]-  where-  w4sym = w4 sym-  (~>) = (,)--  nonInfixTable =-    [ "fpNaN"       ~> fpConst (W4.fpNaN w4sym)-    , "fpPosInf"    ~> fpConst (W4.fpPosInf w4sym)-    , "fpFromBits"  ~> ilam \e -> ilam \p -> wlam sym \w ->-                       VFloat <$> liftIO (W4.fpFromBinary w4sym e p w)-    , "fpToBits"    ~> ilam \e -> ilam \p -> flam \x ->-                       pure $ VWord (e+p)-                            $ WordVal <$> liftIO (W4.fpToBinary w4sym x)-    , "=.="         ~> ilam \_ -> ilam \_ -> flam \x -> pure $ flam \y ->-                       VBit <$> liftIO (W4.fpEq w4sym x y)-    , "fpIsFinite"  ~> ilam \_ -> ilam \_ -> flam \x ->-                       VBit <$> liftIO do inf <- W4.fpIsInf w4sym x-                                          nan <- W4.fpIsNaN w4sym x-                                          weird <- W4.orPred w4sym inf nan-                                          W4.notPred w4sym weird--    , "fpAdd"       ~> fpBinArithV sym fpPlus-    , "fpSub"       ~> fpBinArithV sym fpMinus-    , "fpMul"       ~> fpBinArithV sym fpMult-    , "fpDiv"       ~> fpBinArithV sym fpDiv--    , "fpFromRational" ~>-       ilam \e -> ilam \p -> wlam sym \r -> pure $ lam \x ->-       do rat <- fromVRational <$> x-          VFloat <$> fpCvtFromRational sym e p r rat--    , "fpToRational" ~>-       ilam \_e -> ilam \_p -> flam \fp ->-       VRational <$> fpCvtToRational sym fp-    ]------ | A helper for definitng floating point constants.-fpConst ::-  W4.IsSymExprBuilder sym =>-  (Integer -> Integer -> IO (W4.SFloat sym)) ->-  Value sym-fpConst mk =-     ilam \ e ->- VNumPoly \ ~(Nat p) ->- VFloat <$> liftIO (mk e p)
src/Cryptol/IR/FreeVars.hs view
@@ -99,6 +99,7 @@ instance FreeVars Expr where   freeVars expr =     case expr of+      ELocated _r t     -> freeVars t       EList es t        -> freeVars es <> freeVars t       ETuple es         -> freeVars es       ERec fs           -> freeVars (recordElements fs)@@ -139,7 +140,7 @@        TUser _ _ t -> freeVars t       TRec fs     -> freeVars (recordElements fs)-+      TNewtype nt ts -> freeVars nt <> freeVars ts  instance FreeVars TVar where   freeVars tv = case tv of@@ -147,14 +148,11 @@                   _         -> mempty  instance FreeVars TCon where-  freeVars tc =-    case tc of-     TC (TCNewtype (UserTC n _)) -> mempty { tyDeps = Set.singleton n }-     _ -> mempty+  freeVars _tc = mempty  instance FreeVars Newtype where   freeVars nt = foldr rmTParam base (ntParams nt)-    where base = freeVars (ntConstraints nt) <> freeVars (map snd (ntFields nt))+    where base = freeVars (ntConstraints nt) <> freeVars (recordElements (ntFields nt))   --------------------------------------------------------------------------------
src/Cryptol/ModuleSystem.hs view
@@ -14,6 +14,7 @@   , DynamicEnv(..)   , ModuleError(..), ModuleWarning(..)   , ModuleCmd, ModuleRes+  , ModuleInput(..)   , findModule   , loadModuleByPath   , loadModuleByName@@ -32,7 +33,6 @@   , IfaceTySyn, IfaceDecl(..)   ) where -import qualified Cryptol.Eval as E import qualified Cryptol.Eval.Concrete as Concrete import           Cryptol.ModuleSystem.Env import           Cryptol.ModuleSystem.Interface@@ -46,11 +46,9 @@ import qualified Cryptol.TypeCheck.AST     as T import qualified Cryptol.Utils.Ident as M -import Data.ByteString (ByteString)- -- Public Interface ------------------------------------------------------------ -type ModuleCmd a = (E.EvalOpts, FilePath -> IO ByteString, ModuleEnv) -> IO (ModuleRes a)+type ModuleCmd a = ModuleInput IO -> IO (ModuleRes a)  type ModuleRes a = (Either ModuleError (a,ModuleEnv), [ModuleWarning]) @@ -63,8 +61,8 @@  -- | Load the module contained in the given file. loadModuleByPath :: FilePath -> ModuleCmd (ModulePath,T.Module)-loadModuleByPath path (evo, byteReader, env) =-  runModuleM (evo, byteReader, resetModuleEnv env) $ do+loadModuleByPath path minp =+  runModuleM minp{ minpModuleEnv = resetModuleEnv (minpModuleEnv minp) } $ do     unloadModule ((InFile path ==) . lmFilePath)     m <- Base.loadModuleByPath path     setFocusedModule (T.mName m)@@ -72,8 +70,8 @@  -- | Load the given parsed module. loadModuleByName :: P.ModName -> ModuleCmd (ModulePath,T.Module)-loadModuleByName n (evo, byteReader, env) =-  runModuleM (evo, byteReader, resetModuleEnv env) $ do+loadModuleByName n minp =+  runModuleM minp{ minpModuleEnv = resetModuleEnv (minpModuleEnv minp) } $ do     unloadModule ((n ==) . lmName)     (path,m') <- Base.loadModuleFrom False (FromModule n)     setFocusedModule (T.mName m')
src/Cryptol/ModuleSystem/Base.hs view
@@ -26,7 +26,6 @@                                 , ModContext(..)                                 , ModulePath(..), modulePathLabel) import qualified Cryptol.Eval                 as E- import qualified Cryptol.Eval.Concrete as Concrete import           Cryptol.Eval.Concrete (Concrete(..)) import qualified Cryptol.ModuleSystem.NamingEnv as R@@ -41,6 +40,7 @@ import qualified Cryptol.TypeCheck.AST as T import qualified Cryptol.TypeCheck.PP as T import qualified Cryptol.TypeCheck.Sanity as TcSanity+ import Cryptol.Transform.AddModParams (addModParams) import Cryptol.Utils.Ident ( preludeName, floatName, arrayName, suiteBName, primeECName                            , preludeReferenceName, interactiveName, modNameChunks@@ -203,8 +203,10 @@      tcm <- optionalInstantiate =<< checkModule isrc path pm       -- extend the eval env, unless a functor.-     tbl <- Concrete.primTable <$> getEvalOpts+     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 @@ -453,7 +455,7 @@  data TCLinter o = TCLinter   { lintCheck ::-      o -> T.InferInput -> Either TcSanity.Error [TcSanity.ProofObligation]+      o -> T.InferInput -> Either (Range, TcSanity.Error) [TcSanity.ProofObligation]   , lintModule :: Maybe P.ModName   } @@ -465,7 +467,9 @@         Left err     -> Left err         Right (s1,os)           | TcSanity.same s s1  -> Right os-          | otherwise -> Left (TcSanity.TypeMismatch "exprLinter" s s1)+          | otherwise -> Left ( fromMaybe emptyRange (getLoc e')+                              , TcSanity.TypeMismatch "exprLinter" s s1+                              )   , lintModule = Nothing   } @@ -524,14 +528,15 @@          typeCheckingFailed nameMap errs  -- | Generate input for the typechecker.-genInferInput :: Range -> PrimMap ->-                          IfaceParams -> IfaceDecls -> ModuleM T.InferInput+genInferInput :: Range -> PrimMap -> IfaceParams -> IfaceDecls -> ModuleM T.InferInput 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   return T.InferInput@@ -542,6 +547,7 @@     , T.inpAbstractTypes = ifAbstractTypes env     , T.inpNameSeeds = seeds     , T.inpMonoBinds = monoBinds+    , T.inpCallStacks = callStacks     , T.inpSolverConfig = cfg     , T.inpSearchPath = searchPath     , T.inpSupply    = supply@@ -549,30 +555,37 @@     , T.inpParamTypes       = ifParamTypes params     , T.inpParamConstraints = ifParamConstraints params     , T.inpParamFuns        = ifParamFuns params+    , T.inpSolver           = solver     }  - -- Evaluation ------------------------------------------------------------------  evalExpr :: T.Expr -> ModuleM Concrete.Value evalExpr e = do   env <- getEvalEnv   denv <- getDynEnv-  evopts <- getEvalOpts+  evopts <- getEvalOptsAction   let tbl = Concrete.primTable evopts   let ?evalPrim = \i -> Right <$> Map.lookup i tbl-  io $ E.runEval $ (E.evalExpr Concrete (env <> deEnv denv) e)+  let ?range = emptyRange+  callStacks <- getCallStacks+  let ?callStacks = callStacks +  io $ E.runEval mempty (E.evalExpr Concrete (env <> deEnv denv) e)+ evalDecls :: [T.DeclGroup] -> ModuleM () evalDecls dgs = do   env <- getEvalEnv   denv <- getDynEnv-  evOpts <- getEvalOpts+  evOpts <- getEvalOptsAction   let env' = env <> deEnv denv   let tbl = Concrete.primTable evOpts   let ?evalPrim = \i -> Right <$> Map.lookup i tbl-  deEnv' <- io $ E.runEval $ E.evalDecls Concrete dgs env'+  callStacks <- getCallStacks+  let ?callStacks = callStacks++  deEnv' <- io $ E.runEval mempty (E.evalDecls Concrete dgs env')   let denv' = denv { deDecls = deDecls denv ++ dgs                    , deEnv = deEnv'                    }
src/Cryptol/ModuleSystem/Env.hs view
@@ -177,6 +177,12 @@ loadedNonParamModules :: ModuleEnv -> [T.Module] loadedNonParamModules = map lmModule . lmLoadedModules . meLoadedModules +loadedNewtypes :: ModuleEnv -> Map Name IfaceNewtype+loadedNewtypes menv = Map.unions+   [ ifNewtypes (ifPublic i) <> ifNewtypes (ifPrivate i)+   | i <- map lmInterface (getLoadedModules (meLoadedModules menv))+   ]+ -- | Are any parameterized modules loaded? hasParamModules :: ModuleEnv -> Bool hasParamModules = not . null . lmLoadedParamModules . meLoadedModules
src/Cryptol/ModuleSystem/InstantiateModule.hs view
@@ -183,6 +183,7 @@                     Just y -> EVar y                     _      -> expr +        ELocated r e              -> ELocated r (inst env e)         EList xs t                -> EList (inst env xs) (inst env t)         ETuple es                 -> ETuple (inst env es)         ERec xs                   -> ERec (fmap go xs)@@ -243,6 +244,7 @@       TUser x ts t  -> TUser y (inst env ts) (inst env t)         where y = Map.findWithDefault x x (tyNameMap env)       TRec fs       -> TRec (fmap (inst env) fs)+      TNewtype nt ts -> TNewtype (inst env nt) (inst env ts)  instance Inst TCon where   inst env tc =@@ -253,7 +255,6 @@ instance Inst TC where   inst env tc =     case tc of-      TCNewtype x  -> TCNewtype (inst env x)       TCAbstract x -> TCAbstract (inst env x)       _            -> tc @@ -281,7 +282,7 @@   inst env nt = Newtype { ntName = instTyName env x                         , ntParams = ntParams nt                         , ntConstraints = inst env (ntConstraints nt)-                        , ntFields = [ (f,inst env t) | (f,t) <- ntFields nt ]+                        , ntFields = fmap (inst env) (ntFields nt)                         , ntDoc = ntDoc nt                         }     where x = ntName nt
src/Cryptol/ModuleSystem/Monad.hs view
@@ -29,6 +29,8 @@ import qualified Cryptol.Parser.NoInclude as NoInc import qualified Cryptol.TypeCheck as T import qualified Cryptol.TypeCheck.AST as T+import qualified Cryptol.TypeCheck.Solver.SMT as SMT+ import           Cryptol.Parser.Position (Range) import           Cryptol.Utils.Ident (interactiveName, noModuleName) import           Cryptol.Utils.PP@@ -39,6 +41,7 @@ import Control.Exception (IOException) import Data.ByteString (ByteString) import Data.Function (on)+import Data.Map (Map) import Data.Maybe (isJust) import Data.Text.Encoding.Error (UnicodeException) import MonadLib@@ -300,13 +303,20 @@  data RO m =   RO { roLoading    :: [ImportSource]-     , roEvalOpts   :: EvalOpts+     , roEvalOpts   :: m EvalOpts+     , roCallStacks :: Bool      , roFileReader :: FilePath -> m ByteString+     , roTCSolver   :: SMT.Solver      } -emptyRO :: EvalOpts -> (FilePath -> m ByteString) -> RO m-emptyRO ev fileReader =-  RO { roLoading = [], roEvalOpts = ev, roFileReader = fileReader }+emptyRO :: ModuleInput m -> RO m+emptyRO minp =+  RO { roLoading = []+     , roEvalOpts   = minpEvalOpts minp+     , roCallStacks = minpCallStacks minp+     , roFileReader = minpByteReader minp+     , roTCSolver   = minpTCSolver minp+     }  newtype ModuleT m a = ModuleT   { unModuleT :: ReaderT (RO m)@@ -351,21 +361,34 @@ instance MonadIO m => MonadIO (ModuleT m) where   liftIO m = lift $ liftIO m -runModuleT :: Monad m-           => (EvalOpts, FilePath -> m ByteString, ModuleEnv)-           -> ModuleT m a-           -> m (Either ModuleError (a, ModuleEnv), [ModuleWarning])-runModuleT (ev, byteReader, env) m =++data ModuleInput m =+  ModuleInput+  { minpCallStacks :: Bool+  , minpEvalOpts   :: m EvalOpts+  , minpByteReader :: FilePath -> m ByteString+  , minpModuleEnv  :: ModuleEnv+  , minpTCSolver   :: SMT.Solver+  }++runModuleT ::+  Monad m =>+  ModuleInput m ->+  ModuleT m a ->+  m (Either ModuleError (a, ModuleEnv), [ModuleWarning])+runModuleT minp m =     runWriterT   $ runExceptionT-  $ runStateT env-  $ runReaderT (emptyRO ev byteReader)+  $ runStateT (minpModuleEnv minp)+  $ runReaderT (emptyRO minp)   $ unModuleT m  type ModuleM = ModuleT IO -runModuleM :: (EvalOpts, FilePath -> IO ByteString, ModuleEnv) -> ModuleM a-           -> IO (Either ModuleError (a,ModuleEnv),[ModuleWarning])+runModuleM ::+  ModuleInput IO ->+  ModuleM a ->+  IO (Either ModuleError (a,ModuleEnv),[ModuleWarning]) runModuleM = runModuleT  @@ -377,6 +400,9 @@   RO { roFileReader = readFileBytes } <- ask   return readFileBytes +getCallStacks :: Monad m => ModuleT m Bool+getCallStacks = ModuleT (roCallStacks <$> ask)+ readBytes :: Monad m => FilePath -> ModuleT m ByteString readBytes fn = do   fileReader <- getByteReader@@ -385,6 +411,9 @@ getModuleEnv :: Monad m => ModuleT m ModuleEnv getModuleEnv = ModuleT get +getTCSolver :: Monad m => ModuleT m SMT.Solver+getTCSolver = ModuleT (roTCSolver <$> ask)+ setModuleEnv :: Monad m => ModuleEnv -> ModuleT m () setModuleEnv = ModuleT . set @@ -489,15 +518,23 @@ modifyEvalEnv f = ModuleT $ do   env <- get   let evalEnv = meEvalEnv env-  evalEnv' <- inBase $ E.runEval (f evalEnv)+  evalEnv' <- inBase $ E.runEval mempty (f evalEnv)   set $! env { meEvalEnv = evalEnv' }  getEvalEnv :: ModuleM EvalEnv getEvalEnv  = ModuleT (meEvalEnv `fmap` get) +getEvalOptsAction :: ModuleM (IO EvalOpts)+getEvalOptsAction = ModuleT (roEvalOpts `fmap` ask)+ getEvalOpts :: ModuleM EvalOpts-getEvalOpts = ModuleT (roEvalOpts `fmap` ask)+getEvalOpts =+  do act <- getEvalOptsAction+     liftIO act +getNewtypes :: ModuleM (Map T.Name T.Newtype)+getNewtypes = ModuleT (loadedNewtypes <$> get)+ getFocusedModule :: ModuleM (Maybe P.ModName) getFocusedModule  = ModuleT (meFocusedModule `fmap` get) @@ -547,4 +584,3 @@ withLogger :: (Logger -> a -> IO b) -> a -> ModuleM b withLogger f a = do l <- getEvalOpts                     io (f (evalLogger l) a)-
src/Cryptol/ModuleSystem/Name.hs view
@@ -57,7 +57,6 @@   import           Control.DeepSeq-import           Control.Monad.Fix (MonadFix(mfix)) import qualified Data.Map as Map import qualified Data.Monoid as M import           Data.Ord (comparing)@@ -294,9 +293,6 @@ instance RunM m (a,Supply) r => RunM (SupplyT m) a (Supply -> r) where   runM (SupplyT m) s = runM m s   {-# INLINE runM #-}--instance MonadFix m => MonadFix (SupplyT m) where-  mfix f = SupplyT (mfix (unSupply . f))  -- | Retrieve the next unique from the supply. nextUniqueM :: FreshM m => m Int
src/Cryptol/ModuleSystem/Renamer.hs view
@@ -501,7 +501,7 @@     name' <- rnLocated renameType (nName n)     shadowNames (nParams n) $       do ps'   <- traverse rename (nParams n)-         body' <- traverse (rnNamed rename) (nBody n)+         body' <- traverse (traverse rename) (nBody n)          return Newtype { nName   = name'                         , nParams = ps'                         , nBody   = body' }@@ -693,13 +693,18 @@        case more of          [] -> case h of                  UpdSet -> UpdField UpdSet [l] <$> rename e-                 UpdFun -> UpdField UpdFun [l] <$> rename (EFun [PVar p] e)+                 UpdFun -> UpdField UpdFun [l] <$> rename (EFun emptyFunDesc [PVar p] e)                        where                        p = UnQual . selName <$> last ls          _ -> UpdField UpdFun [l] <$> rename (EUpd Nothing [ UpdField h more e])       [] -> panic "rename@UpdField" [ "Empty label list." ]  +instance Rename FunDesc where+  rename (FunDesc nm offset) =+    do nm' <- traverse renameVar nm+       pure (FunDesc nm' offset)+ instance Rename Expr where   rename expr = case expr of     EVar n          -> EVar <$> renameVar n@@ -719,6 +724,10 @@                                <*> traverse rename n                                <*> rename e                                <*> traverse rename t+    EFromToLessThan s e t ->+                       EFromToLessThan <$> rename s+                                       <*> rename e+                                       <*> traverse rename t     EInfFrom a b    -> EInfFrom<$> rename a  <*> traverse rename b     EComp e' bs     -> do arms' <- traverse renameArm bs                           let (envs,bs') = unzip arms'@@ -733,10 +742,11 @@                             EWhere <$> rename e' <*> traverse rename ds     ETyped e' ty    -> ETyped  <$> rename e' <*> rename ty     ETypeVal ty     -> ETypeVal<$> rename ty-    EFun ps e'      -> do (env,ps') <- renamePats ps+    EFun desc ps e' -> do desc' <- rename desc+                          (env,ps') <- renamePats ps                           -- NOTE: renamePats will generate warnings, so we don't                           -- need to duplicate them here-                          shadowNames' CheckNone env (EFun ps' <$> rename e')+                          shadowNames' CheckNone env (EFun desc' ps' <$> rename e')     ELocated e' r   -> withLoc r                      $ ELocated <$> rename e' <*> pure r @@ -966,10 +976,3 @@                              <*> pure f                              <*> traverse rename ps                              <*> traverse rename cs----- Utilities ---------------------------------------------------------------------rnNamed :: (a -> RenameM b) -> Named a -> RenameM (Named b)-rnNamed  = traverse-{-# INLINE rnNamed #-}
src/Cryptol/Parser.y view
@@ -27,6 +27,7 @@  import           Control.Applicative as A import           Data.Maybe(fromMaybe)+import           Data.List.NonEmpty ( NonEmpty(..), cons ) import           Data.Text(Text) import qualified Data.Text as T import           Control.Monad(liftM2,msum)@@ -37,6 +38,7 @@ import Cryptol.Parser.ParserUtils import Cryptol.Parser.Unlit(PreProc(..), guessPreProc) import Cryptol.Utils.Ident(paramInstModName)+import Cryptol.Utils.RecordMap(RecordMap)  import Paths_cryptol }@@ -91,7 +93,9 @@   '<-'        { Located $$ (Token (Sym ArrL    ) _)}   '..'        { Located $$ (Token (Sym DotDot  ) _)}   '...'       { Located $$ (Token (Sym DotDotDot) _)}+  '..<'       { Located $$ (Token (Sym DotDotLt) _)}   '|'         { Located $$ (Token (Sym Bar     ) _)}+  '<'         { Located $$ (Token (Sym Lt      ) _)}    '('         { Located $$ (Token (Sym ParenL  ) _)}   ')'         { Located $$ (Token (Sym ParenR  ) _)}@@ -325,13 +329,13 @@  newtype                 :: { Newtype PName }   : 'newtype' qname '=' newtype_body-                           { Newtype { nName = $2, nParams = [], nBody = $4 } }+                           { Newtype $2 [] (thing $4) }   | 'newtype' qname tysyn_params '=' newtype_body-                           { Newtype { nName = $2, nParams = $3, nBody = $5 } }+                           { Newtype $2 (reverse $3) (thing $5) } -newtype_body            :: { [Named (Type PName)] }-  : '{' '}'                { [] }-  | '{' field_types '}'    { $2 }+newtype_body            :: { Located (RecordMap Ident (Range, Type PName)) }+  : '{' '}'                {% mkRecord (rComb $1 $2) (Located emptyRange) [] }+  | '{' field_types '}'    {% mkRecord (rComb $1 $3) (Located emptyRange) $2 }  vars_comma                 :: { [ LPName ]  }   : var                       { [ $1]      }@@ -402,6 +406,7 @@   | '-'                             { Located $1 $ mkUnqual $ mkInfix "-" }   | '~'                             { Located $1 $ mkUnqual $ mkInfix "~" }   | '^^'                            { Located $1 $ mkUnqual $ mkInfix "^^" }+  | '<'                             { Located $1 $ mkUnqual $ mkInfix "<" }   other_op                         :: { LPName }@@ -424,7 +429,7 @@  -- | An expression without a `where` clause exprNoWhere                    :: { Expr PName }-  : simpleExpr qop longRHS        { at ($1,$3) (binOp $1 $2 $3) }+  : simpleExpr qop longRHS        { binOp $1 $2 $3 }   | longRHS                       { $1 }   | typedExpr                     { $1 } @@ -441,13 +446,13 @@  -- A possibly infix expression (no where, no long application, no type annot) simpleExpr                     :: { Expr PName }-  : simpleExpr qop simpleRHS      { at ($1,$3) (binOp $1 $2 $3) }+  : simpleExpr qop simpleRHS      { binOp $1 $2 $3 }   | simpleRHS                     { $1 }  -- An expression without an obvious end marker longExpr                       :: { Expr PName }   : 'if' ifBranches 'else' exprNoWhere   { at ($1,$4) $ mkIf (reverse $2) $4 }-  | '\\' apats '->' exprNoWhere          { at ($1,$4) $ EFun (reverse $2) $4 }+  | '\\' apats '->' exprNoWhere          { at ($1,$4) $ EFun emptyFunDesc (reverse $2) $4 }  ifBranches                     :: { [(Expr PName, Expr PName)] }   : ifBranch                      { [$1] }@@ -469,7 +474,7 @@  -- Prefix application expression, ends with an atom. simpleApp                      :: { Expr PName }-  : aexprs                        { mkEApp $1 }+  : aexprs                        {% mkEApp $1 }  -- Prefix application expression, may end with a long expression longApp                        :: { Expr PName }@@ -477,9 +482,9 @@   | longExpr                      { $1 }   | simpleApp                     { $1 } -aexprs                         :: { [Expr PName] }-  : aexpr                         { [$1] }-  | aexprs aexpr                  { $2 : $1 }+aexprs                         :: { NonEmpty (Expr PName) }+  : aexpr                         { $1 :| [] }+  | aexprs aexpr                  { cons $2 $1 }   -- Expression atom (needs no parens)@@ -567,6 +572,9 @@    | expr          '..' expr       {% eFromTo $2 $1 Nothing   $3 }   | expr ',' expr '..' expr       {% eFromTo $4 $1 (Just $3) $5 }++  | expr '..' '<' expr            {% eFromToLessThan $2 $1 $4   }+  | expr '..<'    expr            {% eFromToLessThan $2 $1 $3   }    | expr '...'                    { EInfFrom $1 Nothing         }   | expr ',' expr '...'           { EInfFrom $1 (Just $3)       }
src/Cryptol/Parser/AST.hs view
@@ -68,6 +68,8 @@   , TypeInst(..)   , UpdField(..)   , UpdHow(..)+  , FunDesc(..)+  , emptyFunDesc      -- * Positions   , Located(..)@@ -246,7 +248,7 @@  data Newtype name = Newtype { nName   :: Located name        -- ^ Type name                             , nParams :: [TParam name]       -- ^ Type params-                            , nBody   :: [Named (Type name)] -- ^ Constructor+                            , nBody   :: Rec (Type name)     -- ^ Body                             } deriving (Eq, Show, Generic, NFData)  -- | A declaration for a type with no implementation.@@ -312,6 +314,9 @@               | EList [Expr n]                  -- ^ @ [1,2,3] @               | EFromTo (Type n) (Maybe (Type n)) (Type n) (Maybe (Type n))                                                 -- ^ @ [1, 5 .. 117 : t] @+              | EFromToLessThan (Type n) (Type n) (Maybe (Type n))+                                                -- ^ @ [ 1 .. < 10 : t ] @+               | EInfFrom (Expr n) (Maybe (Expr n))-- ^ @ [1, 3 ...] @               | EComp (Expr n) [[Match n]]      -- ^ @ [ 1 | x <- xs ] @               | EApp (Expr n) (Expr n)          -- ^ @ f x @@@ -320,7 +325,7 @@               | EWhere (Expr n) [Decl n]        -- ^ @ 1 + x where { x = 2 } @               | ETyped (Expr n) (Type n)        -- ^ @ 1 : [8] @               | ETypeVal (Type n)               -- ^ @ `(x + 1)@, @x@ is a type-              | EFun [Pattern n] (Expr n)       -- ^ @ \\x y -> x @+              | EFun (FunDesc n) [Pattern n] (Expr n) -- ^ @ \\x y -> x @               | ELocated (Expr n) Range         -- ^ position annotation                | ESplit (Expr n)                 -- ^ @ splitAt x @ (Introduced by NoPat)@@ -328,6 +333,19 @@               | EInfix (Expr n) (Located n) Fixity (Expr n)-- ^ @ a + b @ (Removed by Fixity)                 deriving (Eq, Show, Generic, NFData, Functor) +-- | Description of functions.  Only trivial information is provided here+--   by the parser.  The NoPat pass fills this in as required.+data FunDesc n =+  FunDesc+  { funDescrName      :: Maybe n   -- ^ Name of this function, if it has one+  , funDescrArgOffset :: Int -- ^ number of previous arguments to this function+                             --   bound in surrounding lambdas (defaults to 0)+  }+ deriving (Eq, Show, Generic, NFData, Functor)++emptyFunDesc :: FunDesc n+emptyFunDesc = FunDesc Nothing 0+ data UpdField n = UpdField UpdHow [Located Selector] (Expr n)                                                 -- ^ non-empty list @ x.y = e@                 deriving (Eq, Show, Generic, NFData, Functor)@@ -394,7 +412,8 @@   instance AddLoc (Expr n) where-  addLoc = ELocated+  addLoc x@ELocated{} _ = x+  addLoc x            r = ELocated x r    dropLoc (ELocated e _) = dropLoc e   dropLoc e              = e@@ -496,7 +515,7 @@     | null locs = Nothing     | otherwise = Just (rCombs locs)     where-    locs = catMaybes [ getLoc (nName n), getLoc (nBody n) ]+    locs = catMaybes ([ getLoc (nName n)] ++ map (Just . fst . snd) (displayFields (nBody n)))   --------------------------------------------------------------------------------@@ -575,7 +594,7 @@ 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 ":") (nBody nt))) ]+    , braces (commaSep (map (ppNamed' ":") (displayFields (nBody nt)))) ]  instance PP Import where   ppPrec _ d = text "import" <+> sep [ pp (iModule d), mbAs, mbSpec ]@@ -732,6 +751,9 @@       EFromTo e1 e2 e3 t1 -> brackets (pp e1 <.> step <+> text ".." <+> end)         where step = maybe empty (\e -> comma <+> pp e) e2               end = maybe (pp e3) (\t -> pp e3 <+> colon <+> pp t) t1+      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))@@ -744,7 +766,7 @@       ESel    e l   -> ppPrec 4 e <.> text "." <.> pp l        -- low prec-      EFun xs e     -> wrap n 0 ((text "\\" <.> hsep (map (ppPrec 3) xs)) <+>+      EFun _ xs e   -> wrap n 0 ((text "\\" <.> hsep (map (ppPrec 3) xs)) <+>                                  text "->" <+> pp e)        EIf e1 e2 e3  -> wrap n 0 $ sep [ text "if"   <+> pp e1@@ -938,7 +960,7 @@ instance NoPos (Newtype name) where   noPos n = Newtype { nName   = noPos (nName n)                     , nParams = nParams n-                    , nBody   = noPos (nBody n)+                    , nBody   = fmap noPos (nBody n)                     }  instance NoPos (Bind name) where@@ -979,6 +1001,7 @@       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)+      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)       EApp  x y       -> EApp     (noPos x) (noPos y)@@ -987,7 +1010,7 @@       EWhere x y      -> EWhere   (noPos x) (noPos y)       ETyped x y      -> ETyped   (noPos x) (noPos y)       ETypeVal x      -> ETypeVal (noPos x)-      EFun x y        -> EFun     (noPos x) (noPos y)+      EFun dsc x y    -> EFun dsc (noPos x) (noPos y)       ELocated x _    -> noPos x        ESplit x        -> ESplit (noPos x)
src/Cryptol/Parser/Lexer.x view
@@ -142,6 +142,7 @@ "`"                       { emit $ Sym BackTick } ".."                      { emit $ Sym DotDot } "..."                     { emit $ Sym DotDotDot }+"..<"                     { emit $ Sym DotDotLt  } "|"                       { emit $ Sym Bar } "("                       { emit $ Sym ParenL } ")"                       { emit $ Sym ParenR }@@ -161,6 +162,9 @@ "*"                       { emit  (Op   Mul  ) } "^^"                      { emit  (Op   Exp  ) } +-- < can appear in the enumeration syntax `[ x .. < y ]+"<"                       { emit $ Sym Lt }+ -- hash is used as a kind, and as a pattern "#"                       { emit  (Op   Hash ) } @@ -202,7 +206,7 @@ primLexer :: Config -> Text -> ([Located Token], Position) primLexer cfg cs = run inp Normal   where-  inp = Inp { alexPos           = start+  inp = Inp { alexPos           = cfgStart cfg             , alexInputPrevChar = '\n'             , input             = unLit (cfgPreProc cfg) cs } 
src/Cryptol/Parser/LexerUtils.hs view
@@ -32,6 +32,7 @@  data Config = Config   { cfgSource      :: !FilePath     -- ^ File that we are working on+  , cfgStart       :: !Position     -- ^ Starting position for the parser   , cfgLayout      :: !Layout       -- ^ Settings for layout processing   , cfgPreProc     :: PreProc       -- ^ Preprocessor settings   , cfgAutoInclude :: [FilePath]    -- ^ Implicit includes@@ -43,6 +44,7 @@ defaultConfig :: Config defaultConfig  = Config   { cfgSource      = ""+  , cfgStart       = start   , cfgLayout      = Layout   , cfgPreProc     = None   , cfgAutoInclude = []@@ -522,12 +524,14 @@               | Dot               | DotDot               | DotDotDot+              | DotDotLt               | Colon               | BackTick               | ParenL   | ParenR               | BracketL | BracketR               | CurlyL   | CurlyR               | TriL     | TriR+              | Lt               | Underscore                 deriving (Eq, Show, Generic, NFData) 
src/Cryptol/Parser/Names.hs view
@@ -84,6 +84,7 @@                      in Set.unions (e : map namesUF fs)     EList es      -> Set.unions (map namesE es)     EFromTo{}     -> 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)                      in Set.union (boundLNames (concat dss) (namesE e))@@ -95,7 +96,7 @@                      in Set.union (boundLNames bs (namesE e)) xs     ETyped e _    -> namesE e     ETypeVal _    -> Set.empty-    EFun ps e     -> boundLNames (namesPs ps) (namesE e)+    EFun _ ps e   -> boundLNames (namesPs ps) (namesE e)     ELocated e _  -> namesE e      ESplit e      -> namesE e@@ -203,6 +204,8 @@                        `Set.union` maybe Set.empty tnamesT b                        `Set.union` tnamesT c                        `Set.union` 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')     EComp e mss     -> Set.union (tnamesE e) (Set.unions (map tnamesM (concat mss)))     EApp e1 e2      -> Set.union (tnamesE e1) (tnamesE e2)@@ -212,7 +215,7 @@                        in Set.union (boundLNames bs (tnamesE e)) xs     ETyped e t      -> Set.union (tnamesE e) (tnamesT t)     ETypeVal t      -> tnamesT t-    EFun ps e       -> Set.union (Set.unions (map tnamesP ps)) (tnamesE e)+    EFun _ ps e     -> Set.union (Set.unions (map tnamesP ps)) (tnamesE e)     ELocated e _    -> tnamesE e      ESplit e        -> tnamesE e
src/Cryptol/Parser/NoPat.hs view
@@ -154,6 +154,7 @@     EUpd mb fs    -> EUpd    <$> traverse noPatE mb <*> traverse noPatUF fs     EList es      -> EList   <$> mapM noPatE es     EFromTo {}    -> return expr+    EFromToLessThan{} -> return expr     EInfFrom e e' -> EInfFrom <$> noPatE e <*> traverse noPatE e'     EComp e mss   -> EComp  <$> noPatE e <*> mapM noPatArm mss     EApp e1 e2    -> EApp   <$> noPatE e1 <*> noPatE e2@@ -162,8 +163,7 @@     EWhere e ds   -> EWhere <$> noPatE e <*> noPatDs ds     ETyped e t    -> ETyped <$> noPatE e <*> return t     ETypeVal {}   -> return expr-    EFun ps e     -> do (ps1,e1) <- noPatFun ps e-                        return (EFun ps1 e1)+    EFun desc ps e -> noPatFun (funDescrName desc) (funDescrArgOffset desc) ps e     ELocated e r1 -> ELocated <$> inRange r1 (noPatE e) <*> return r1      ESplit e      -> ESplit  <$> noPatE e@@ -174,15 +174,26 @@ noPatUF :: UpdField PName -> NoPatM (UpdField PName) noPatUF (UpdField h ls e) = UpdField h ls <$> noPatE e -noPatFun :: [Pattern PName] -> Expr PName -> NoPatM ([Pattern PName], Expr PName)-noPatFun ps e =-  do (xs,bs) <- unzip <$> mapM noPat ps-     e1 <- noPatE e-     let body = case concat bs of-                        [] -> e1-                        ds -> EWhere e1 $ map DBind ds-     return (xs, body)-+-- Desugar lambdas with multiple patterns into a sequence of+-- lambdas with a single, simple pattern each.  Bindings required+-- to simplify patterns are placed inside "where" blocks that are+-- interspersed into the lambdas to ensure that the lexical+-- structure is reliable, with names on the right shadowing names+-- on the left.+noPatFun :: Maybe PName -> Int -> [Pattern PName] -> Expr PName -> NoPatM (Expr PName)+noPatFun _   _      []     e = noPatE e+noPatFun mnm offset (p:ps) e =+  do (p',ds) <- noPat p+     e' <- noPatFun mnm (offset+1) ps e+     let body = case ds of+                  [] -> e'+                  _  -> EWhere e' $ map DBind (reverse ds)+                           --                  ^+                           -- This reverse isn't strictly necessary, but yields more sensible+                           -- variable ordering results from type inference.  I'm not entirely+                           -- sure why.+     let desc = FunDesc mnm offset+     return (EFun desc [p'] body)  noPatArm :: [Match PName] -> NoPatM [Match PName] noPatArm ms = concat <$> mapM noPatM ms@@ -203,8 +214,8 @@                                               , show b ]      DExpr e ->-      do (ps,e') <- noPatFun (bParams b) e-         return b { bParams = ps, bDef = DExpr e' <$ bDef b }+      do e' <- noPatFun (Just (thing (bName b))) 0 (bParams b) e+         return b { bParams = [], bDef = DExpr e' <$ bDef b }  noMatchD :: Decl PName -> NoPatM [Decl PName] noMatchD decl =
src/Cryptol/Parser/ParserUtils.hs view
@@ -17,6 +17,8 @@  import Data.Maybe(fromMaybe) import Data.Bits(testBit,setBit)+import Data.List.NonEmpty ( NonEmpty(..) )+import qualified Data.List.NonEmpty as NE import Control.Monad(liftM,ap,unless,guard) import qualified Control.Monad.Fail as Fail import           Data.Text(Text)@@ -65,7 +67,7 @@   case sTokens s of     t : _ | Err e <- tokenType it ->       Left $ HappyErrorMsg (srcRange t) $-         case e of+        [case e of            UnterminatedComment -> "unterminated comment"            UnterminatedString  -> "unterminated string"            UnterminatedChar    -> "unterminated character"@@ -79,6 +81,7 @@                                     T.unpack (tokenText it)            MalformedSelector   -> "malformed selector: " ++                                     T.unpack (tokenText it)+        ]       where it = thing t      t : more -> unP (k t) cfg p s { sPrevTok = Just t, sTokens = more }@@ -86,7 +89,7 @@  data ParseError = HappyError FilePath         {- Name of source file -}                              (Located Token)  {- Offending token -}-                | HappyErrorMsg Range String+                | HappyErrorMsg Range [String]                 | HappyUnexpected FilePath (Maybe (Located Token)) String                 | HappyOutOfTokens FilePath Position                   deriving (Show, Generic, NFData)@@ -123,7 +126,7 @@   text "Unexpected end of file at:" <+>     text path <.> char ':' <.> pp pos -ppError (HappyErrorMsg p x)  = text "Parse error at" <+> pp p $$ nest 2 (text x)+ppError (HappyErrorMsg p xs)  = text "Parse error at" <+> pp p $$ nest 2 (vcat (map text xs))  ppError (HappyUnexpected path ltok e) =   text "Parse error at" <+>@@ -159,13 +162,13 @@   case sPrevTok s of     Just t  -> Left (HappyError (cfgSource cfg) t)     Nothing ->-      Left (HappyErrorMsg emptyRange "Parse error at the beginning of the file")+      Left (HappyErrorMsg emptyRange ["Parse error at the beginning of the file"]) -errorMessage :: Range -> String -> ParseM a-errorMessage r x = P $ \_ _ _ -> Left (HappyErrorMsg r x)+errorMessage :: Range -> [String] -> ParseM a+errorMessage r xs = P $ \_ _ _ -> Left (HappyErrorMsg r xs)  customError :: String -> Located Token -> ParseM a-customError x t = P $ \_ _ _ -> Left (HappyErrorMsg (srcRange t) x)+customError x t = P $ \_ _ _ -> Left (HappyErrorMsg (srcRange t) [x])  expected :: String -> ParseM a expected x = P $ \cfg _ s ->@@ -231,19 +234,19 @@ intVal tok =   case tokenType (thing tok) of     Num x _ _ -> return x-    _         -> errorMessage (srcRange tok) "Expected an integer"+    _         -> errorMessage (srcRange tok) ["Expected an integer"]  mkFixity :: Assoc -> Located Token -> [LPName] -> ParseM (Decl PName) mkFixity assoc tok qns =   do l <- intVal tok      unless (l >= 1 && l <= 100)-          (errorMessage (srcRange tok) "Fixity levels must be between 1 and 100")+          (errorMessage (srcRange tok) ["Fixity levels must be between 1 and 100"])      return (DFixity (Fixity assoc (fromInteger l)) qns)  fromStrLit :: Located Token -> ParseM (Located String) fromStrLit loc = case tokenType (thing loc) of   StrLit str -> return loc { thing = str }-  _          -> errorMessage (srcRange loc) "Expected a string literal"+  _          -> errorMessage (srcRange loc) ["Expected a string literal"]   validDemotedType :: Range -> Type PName -> ParseM (Type PName)@@ -264,14 +267,14 @@     TParens t    -> validDemotedType rng t     TInfix{}     -> ok -  where bad x = errorMessage rng (x ++ " cannot be demoted.")+  where bad x = errorMessage rng [x ++ " cannot be demoted."]         ok    = return $ at rng ty  -- | Input fields are reversed! mkRecord :: AddLoc b => Range -> (RecordMap Ident (Range, a) -> b) -> [Named a] -> ParseM b mkRecord rng f xs =    case res of-     Left (nm,(nmRng,_)) -> errorMessage nmRng ("Record has repeated field: " ++ show (pp nm))+     Left (nm,(nmRng,_)) -> errorMessage nmRng ["Record has repeated field: " ++ show (pp nm)]      Right r -> pure $ at rng (f r)    where@@ -280,11 +283,14 @@   -- | Input expression are reversed-mkEApp :: [Expr PName] -> Expr PName-mkEApp es@(eLast : _) = at (eFirst,eLast) $ foldl EApp f xs+mkEApp :: NonEmpty (Expr PName) -> ParseM (Expr PName)++mkEApp es@(eLast :| _) =+    do f :| xs <- cvtTypeParams eFirst rest+       pure (at (eFirst,eLast) $ foldl EApp f xs)+   where-  eFirst : rest = reverse es-  f : xs        = cvtTypeParams eFirst rest+  eFirst :| rest = NE.reverse es    {- Type applications are parsed as `ETypeVal (TTyApp fs)` expressions.      Here we associate them with their corresponding functions,@@ -293,23 +299,62 @@      [ f, x, `{ a = 2 }, y ]      becomes      [ f, x ` { a = 2 }, y ]++     The parser associates field and tuple projectors that follow an+     explicit type application onto the TTyApp term, so we also+     have to unwind those projections and reapply them.  For example:++     [ f, x, `{ a = 2 }.f.2, y ]+     becomes+     [ f, (x`{ a = 2 }).f.2, y ]+   -}-  cvtTypeParams e [] = [e]+  cvtTypeParams e [] = pure (e :| [])   cvtTypeParams e (p : ps) =-    case toTypeParam p of-      Just fs -> cvtTypeParams (EAppT e fs) ps-      Nothing -> e : cvtTypeParams p ps+    case toTypeParam p Nothing of+      Nothing -> NE.cons e <$> cvtTypeParams p ps -  toTypeParam e =-    case dropLoc e of-      ETypeVal t -> case dropLoc t of-                      TTyApp fs -> Just (map mkTypeInst fs)-                      _         -> Nothing-      _          ->  Nothing+      Just (fs,ss,rng) ->+        if checkAppExpr e then+          let e'  = foldr (flip ESel) (EAppT e fs) ss+              e'' = case rCombMaybe (getLoc e) rng of+                      Just r -> ELocated e' r+                      Nothing -> e'+           in cvtTypeParams e'' ps+        else+          errorMessage (fromMaybe emptyRange (getLoc e))+                  [ "Explicit type applications can only be applied to named values."+                  , "Unexpected: " ++ show (pp e)+                  ] -mkEApp es        = panic "[Parser] mkEApp" ["Unexpected:", show es]+  {- Check if the given expression is a legal target for explicit type application.+     This is basically only variables, but we also allow the parenthesis and+     the phantom "located" AST node.+   -}+  checkAppExpr e =+    case e of+      ELocated e' _ -> checkAppExpr e'+      EParens e'    -> checkAppExpr e'+      EVar{}        -> True+      _             -> False +  {- Look under a potential chain of selectors to see if we have a TTyApp.+     If so, return the ty app information and the collected selectors+     to reapply.+   -}+  toTypeParam e mr =+    case e of+      ELocated e' rng -> toTypeParam e' (rCombMaybe mr (Just rng))+      ETypeVal t -> toTypeParam' t mr+      ESel e' s  -> ( \(fs,ss,r) -> (fs,s:ss,r) ) <$> toTypeParam e' mr+      _          ->  Nothing +  toTypeParam' t mr =+    case t of+      TLocated t' rng -> toTypeParam' t' (rCombMaybe mr (Just rng))+      TTyApp fs -> Just (map mkTypeInst fs, [], mr)+      _ -> Nothing+ unOp :: Expr PName -> Expr PName -> Expr PName unOp f x = at (f,x) $ EApp f x @@ -325,12 +370,13 @@     (Nothing, Just (e2', t), Nothing) -> eFromToType r e1 (Just e2') e3 (Just t)     (Nothing, Nothing, Just (e3', t)) -> eFromToType r e1 e2 e3' (Just t)     (Nothing, Nothing, Nothing) -> eFromToType r e1 e2 e3 Nothing-    _ -> errorMessage r "A sequence enumeration may have at most one element type annotation."-  where-    asETyped (ELocated e _) = asETyped e-    asETyped (ETyped e t) = Just (e, t)-    asETyped _ = Nothing+    _ -> errorMessage r ["A sequence enumeration may have at most one element type annotation."] +asETyped :: Expr n -> Maybe (Expr n, Type n)+asETyped (ELocated e _) = asETyped e+asETyped (ETyped e t) = Just (e, t)+asETyped _ = Nothing+ eFromToType ::   Range -> Expr PName -> Maybe (Expr PName) -> Expr PName -> Maybe (Type PName) -> ParseM (Expr PName) eFromToType r e1 e2 e3 t =@@ -339,22 +385,40 @@           <*> exprToNumT r e3           <*> pure t +eFromToLessThan ::+  Range -> Expr PName -> Expr PName -> ParseM (Expr PName)+eFromToLessThan r e1 e2 =+  case asETyped e2 of+    Just _  -> errorMessage r ["The exclusive upper bound of an enumeration may not have a type annotation."]+    Nothing ->+      case asETyped e1 of+        Nothing      -> eFromToLessThanType r e1  e2 Nothing+        Just (e1',t) -> eFromToLessThanType r e1' e2 (Just t)++eFromToLessThanType ::+  Range -> Expr PName -> Expr PName -> Maybe (Type PName) -> ParseM (Expr PName)+eFromToLessThanType r e1 e2 t =+  EFromToLessThan+    <$> exprToNumT r e1+    <*> exprToNumT r e2+    <*> pure t+ exprToNumT :: Range -> Expr PName -> ParseM (Type PName) exprToNumT r expr =   case translateExprToNumT expr of     Just t -> return t     Nothing -> bad   where-  bad = errorMessage (fromMaybe r (getLoc expr)) $ unlines+  bad = errorMessage (fromMaybe r (getLoc expr))         [ "The boundaries of .. sequences should be valid numeric types."-        , "The expression `" ++ show expr ++ "` is not."+        , "The expression `" ++ show (pp expr) ++ "` is not."         ]   -- | WARNING: This is a bit of a hack. -- It is used to represent anonymous type applications. anonTyApp :: Maybe Range -> [Type PName] -> Type PName-anonTyApp ~(Just r) ts = TTyApp (map toField ts)+anonTyApp ~(Just r) ts = TLocated (TTyApp (map toField ts)) r   where noName    = Located { srcRange = r, thing = mkIdent (T.pack "") }         toField t = Named { name = noName, value = t } @@ -413,13 +477,13 @@  mkTParam :: Located Ident -> Maybe Kind -> ParseM (TParam PName) mkTParam Located { srcRange = rng, thing = n } k-  | n == widthIdent = errorMessage rng "`width` is not a valid type parameter name."+  | n == widthIdent = errorMessage rng ["`width` is not a valid type parameter name."]   | otherwise       = return (TParam (mkUnqual n) k (Just rng))  mkTySyn :: Located PName -> [TParam PName] -> Type PName -> ParseM (Decl PName) mkTySyn ln ps b   | getIdent (thing ln) == widthIdent =-    errorMessage (srcRange ln) "`width` is not a valid type synonym name."+    errorMessage (srcRange ln) ["`width` is not a valid type synonym name."]    | otherwise =     return $ DType $ TySyn ln Nothing ps b@@ -427,7 +491,7 @@ mkPropSyn :: Located PName -> [TParam PName] -> Type PName -> ParseM (Decl PName) mkPropSyn ln ps b   | getIdent (thing ln) == widthIdent =-    errorMessage (srcRange ln) "`width` is not a valid constraint synonym name."+    errorMessage (srcRange ln) ["`width` is not a valid constraint synonym name."]    | otherwise =     DProp . PropSyn ln Nothing ps . thing <$> mkProp b@@ -436,12 +500,12 @@ polyTerm rng k p   | k == 0          = return (False, p)   | k == 1          = return (True, p)-  | otherwise       = errorMessage rng "Invalid polynomial coefficient"+  | otherwise       = errorMessage rng ["Invalid polynomial coefficient"]  mkPoly :: Range -> [ (Bool,Integer) ] -> ParseM (Expr PName) mkPoly rng terms   | w <= toInteger (maxBound :: Int) = mk 0 (map fromInteger bits)-  | otherwise = errorMessage rng ("Polynomial literal too large: " ++ show w)+  | otherwise = errorMessage rng ["Polynomial literal too large: " ++ show w]    where   w    = case terms of@@ -455,8 +519,7 @@    mk res (n : ns)     | testBit res n = errorMessage rng-                       ("Polynomial contains multiple terms with exponent "-                                                                    ++ show n)+                       ["Polynomial contains multiple terms with exponent " ++ show n]     | otherwise     = mk (setBit res n) ns  @@ -495,11 +558,11 @@ mkIndexedExpr :: ([Pattern PName], [Pattern PName]) -> Expr PName -> Expr PName mkIndexedExpr (ps, ixs) body   | null ps = mkGenerate (reverse ixs) body-  | otherwise = EFun (reverse ps) (mkGenerate (reverse ixs) body)+  | otherwise = EFun emptyFunDesc (reverse ps) (mkGenerate (reverse ixs) body)  mkGenerate :: [Pattern PName] -> Expr PName -> Expr PName mkGenerate pats body =-  foldr (\pat e -> EGenerate (EFun [pat] e)) body pats+  foldr (\pat e -> EGenerate (EFun emptyFunDesc [pat] e)) body pats  mkIf :: [(Expr PName, Expr PName)] -> Expr PName -> Expr PName mkIf ifThens theElse = foldr addIfThen theElse ifThens@@ -540,17 +603,17 @@     Just (n,xs) ->       do vs <- mapM tpK as          unless (distinct (map fst vs)) $-            errorMessage schema_rng "Repeated parameters."+            errorMessage schema_rng ["Repeated parameters."]          let kindMap = Map.fromList vs              lkp v = case Map.lookup (thing v) kindMap of                        Just (k,tp)  -> pure (k,tp)                        Nothing ->                         errorMessage                             (srcRange v)-                            ("Undefined parameter: " ++ show (pp (thing v)))+                            ["Undefined parameter: " ++ show (pp (thing v))]          (as',ins) <- unzip <$> mapM lkp xs          unless (length vs == length xs) $-           errorMessage schema_rng "All parameters should appear in the type."+           errorMessage schema_rng ["All parameters should appear in the type."]           let ki = finK { thing = foldr KFun (thing finK) ins } @@ -565,7 +628,7 @@                  }               ] -    Nothing -> errorMessage schema_rng "Invalid primitive signature"+    Nothing -> errorMessage schema_rng ["Invalid primitive signature"]    where   splitT r ty = case ty of@@ -592,7 +655,7 @@              Just k  -> pure (tpName tp, (tp,k))              Nothing ->               case tpRange tp of-                Just r -> errorMessage r "Parameters need a kind annotation"+                Just r -> errorMessage r ["Parameters need a kind annotation"]                 Nothing -> panic "mkPrimTypeDecl"                               [ "Missing range on schema parameter." ] @@ -671,7 +734,7 @@       TTyApp{}  -> err      where-    err = errorMessage r "Invalid constraint"+    err = errorMessage r ["Invalid constraint"]  -- | Make an ordinary module mkModule :: Located ModName ->@@ -708,7 +771,7 @@     (UpdSet, [l]) | RecordSel i Nothing <- thing l ->       pure Named { name = l { thing = i }, value = e }     _ -> errorMessage (srcRange (head ls))-            "Invalid record field.  Perhaps you meant to update a record?"+            ["Invalid record field.  Perhaps you meant to update a record?"]  exprToFieldPath :: Expr PName -> ParseM [Located Selector] exprToFieldPath e0 = reverse <$> go noLoc e0@@ -744,7 +807,7 @@                          }                ] -      _ -> errorMessage loc "Invalid label in record update."+      _ -> errorMessage loc ["Invalid label in record update."]   mkSelector :: Token -> Selector@@ -754,4 +817,3 @@     Selector (RecordSelectorTok t) -> RecordSel (mkIdent t) Nothing     _ -> panic "mkSelector"           [ "Unexpected selector token", show tok ]-
src/Cryptol/Parser/Position.hs view
@@ -57,6 +57,11 @@   where rFrom = min (from r1) (from r2)         rTo   = max (to r1)   (to r2) +rCombMaybe :: Maybe Range -> Maybe Range -> Maybe Range+rCombMaybe Nothing y = y+rCombMaybe x Nothing = x+rCombMaybe (Just x) (Just y) = Just (rComb x y)+ rCombs :: [Range] -> Range rCombs  = foldl1 rComb @@ -123,5 +128,4 @@ combLoc f l1 l2 = Located { srcRange = rComb (srcRange l1) (srcRange l2)                           , thing    = f (thing l1) (thing l2)                           }- 
src/Cryptol/REPL/Command.hs view
@@ -6,6 +6,8 @@ -- Stability   :  provisional -- Portability :  portable +{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BlockArguments #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-}@@ -34,7 +36,8 @@   , replCheckExpr      -- Check, SAT, and prove-  , qcCmd, QCMode(..)+  , TestReport(..)+  , qcExpr, qcCmd, QCMode(..)   , satCmd   , proveCmd   , onlineProveSat@@ -72,6 +75,7 @@ import Cryptol.Parser     (parseExprWith,parseReplWith,ParseError(),Config(..),defaultConfig     ,parseModName,parseHelpName)+import           Cryptol.Parser.Position (Position(..),Range(..),HasLoc(..)) import qualified Cryptol.TypeCheck.AST as T import qualified Cryptol.TypeCheck.Error as T import qualified Cryptol.TypeCheck.Parseable as T@@ -135,7 +139,7 @@  -- | Commands. data Command-  = Command (REPL ())         -- ^ Successfully parsed command+  = Command (Int -> Maybe FilePath -> REPL ())         -- ^ Successfully parsed command   | Ambiguous String [String] -- ^ Ambiguous command, list of conflicting                               --   commands   | Unknown String            -- ^ The unknown command@@ -159,8 +163,8 @@   compare = compare `on` cNames  data CommandBody-  = ExprArg     (String   -> REPL ())-  | FileExprArg (FilePath -> String -> REPL ())+  = ExprArg     (String   -> (Int,Int) -> Maybe FilePath -> REPL ())+  | FileExprArg (FilePath -> String -> (Int,Int) -> Maybe FilePath -> REPL ())   | DeclsArg    (String   -> REPL ())   | ExprTypeArg (String   -> REPL ())   | ModNameArg  (String   -> REPL ())@@ -214,10 +218,10 @@   , CommandDescr [ ":s", ":set" ] ["[ OPTION [ = VALUE ] ]"] (OptionArg setOptionCmd)     "Set an environmental option (:set on its own displays current values)."     ""-  , CommandDescr [ ":check" ] ["[ EXPR ]"] (ExprArg (void . qcCmd QCRandom))+  , CommandDescr [ ":check" ] ["[ EXPR ]"] (ExprArg (qcCmd QCRandom))     "Use random testing to check that the argument always returns true.\n(If no argument, check all properties.)"     ""-  , CommandDescr [ ":exhaust" ] ["[ EXPR ]"] (ExprArg (void . qcCmd QCExhaust))+  , CommandDescr [ ":exhaust" ] ["[ EXPR ]"] (ExprArg (qcCmd QCExhaust))     "Use exhaustive testing to prove that the argument always returns\ntrue. (If no argument, check all properties.)"     ""   , CommandDescr [ ":prove" ] ["[ EXPR ]"] (ExprArg proveCmd)@@ -295,10 +299,10 @@ -- Command Evaluation ----------------------------------------------------------  -- | Run a command.-runCommand :: Command -> REPL CommandExitCode-runCommand c = case c of+runCommand :: Int -> Maybe FilePath -> Command -> REPL CommandExitCode+runCommand lineNum mbBatch c = case c of -  Command cmd -> (cmd >> return CommandOk) `Cryptol.REPL.Monad.catch` handler+  Command cmd -> (cmd lineNum mbBatch >> return CommandOk) `Cryptol.REPL.Monad.catch` handler     where     handler re = rPutStrLn "" >> rPrint (pp re) >> return CommandError @@ -311,36 +315,9 @@     return CommandError  --- Get the setting we should use for displaying values.-getPPValOpts :: REPL E.PPOpts-getPPValOpts =-  do base      <- getKnownUser "base"-     ascii     <- getKnownUser "ascii"-     infLength <- getKnownUser "infLength"--     fpBase    <- getKnownUser "fp-base"-     fpFmtTxt  <- getKnownUser "fp-format"-     let fpFmt = case parsePPFloatFormat fpFmtTxt of-                   Just f  -> f-                   Nothing -> panic "getPPValOpts"-                                      [ "Failed to parse fp-format" ]--     return E.PPOpts { E.useBase      = base-                     , E.useAscii     = ascii-                     , E.useInfLength = infLength-                     , E.useFPBase    = fpBase-                     , E.useFPFormat  = fpFmt-                     }--getEvalOpts :: REPL E.EvalOpts-getEvalOpts =-  do ppOpts <- getPPValOpts-     l      <- getLogger-     return E.EvalOpts { E.evalPPOpts = ppOpts, E.evalLogger = l }--evalCmd :: String -> REPL ()-evalCmd str = do-  ri <- replParseInput str+evalCmd :: String -> Int -> Maybe FilePath -> REPL ()+evalCmd str lineNum mbBatch = do+  ri <- replParseInput str lineNum mbBatch   case ri of     P.ExprInput expr -> do       (val,_ty) <- replEvalExpr expr@@ -363,27 +340,25 @@       -- comment or empty input does nothing       pure () -printCounterexample :: CounterExampleType -> P.Expr P.PName -> [Concrete.Value] -> REPL ()-printCounterexample cexTy pexpr vs =+printCounterexample :: CounterExampleType -> Doc -> [Concrete.Value] -> REPL ()+printCounterexample cexTy exprDoc vs =   do ppOpts <- getPPValOpts      docs <- mapM (rEval . E.ppValue Concrete ppOpts) vs-     let doc = ppPrec 3 pexpr -- function application has precedence 3-     rPrint $ hang doc 2 (sep docs) <+>+     rPrint $ hang exprDoc 2 (sep docs) <+>        case cexTy of          SafetyViolation -> text "~> ERROR"          PredicateFalsified -> text "= False" -printSatisfyingModel :: P.Expr P.PName -> [Concrete.Value] -> REPL ()-printSatisfyingModel pexpr vs =+printSatisfyingModel :: Doc -> [Concrete.Value] -> REPL ()+printSatisfyingModel exprDoc vs =   do ppOpts <- getPPValOpts      docs <- mapM (rEval . E.ppValue Concrete ppOpts) vs-     let doc = ppPrec 3 pexpr -- function application has precedence 3-     rPrint $ hang doc 2 (sep docs) <+> text ("= True")+     rPrint $ hang exprDoc 2 (sep docs) <+> text ("= True")  -dumpTestsCmd :: FilePath -> String -> REPL ()-dumpTestsCmd outFile str =-  do expr <- replParseExpr str+dumpTestsCmd :: FilePath -> String -> (Int,Int) -> Maybe FilePath -> REPL ()+dumpTestsCmd outFile str pos fnm =+  do expr <- replParseExpr str pos fnm      (val, ty) <- replEvalExpr expr      ppopts <- getPPValOpts      testNum <- getKnownUser "tests" :: REPL Int@@ -409,28 +384,54 @@  data QCMode = QCRandom | QCExhaust deriving (Eq, Show) + -- | Randomly test a property, or exhaustively check it if the number -- of values in the type under test is smaller than the @tests@ -- environment variable, or we specify exhaustive testing.-qcCmd :: QCMode -> String -> REPL [TestReport]-qcCmd qcMode "" =+qcCmd :: QCMode -> String -> (Int,Int) -> Maybe FilePath -> REPL ()+qcCmd qcMode "" _pos _fnm =   do (xs,disp) <- getPropertyNames      let nameStr x = show (fixNameDisp disp (pp x))      if null xs-        then rPutStrLn "There are no properties in scope." *> return []-        else concat <$> (forM xs $ \x ->+        then rPutStrLn "There are no properties in scope."+        else forM_ xs $ \(x,d) ->                do let str = nameStr x                   rPutStr $ "property " ++ str ++ " "-                  qcCmd qcMode str)+                  let texpr = T.EVar x+                  let schema = M.ifDeclSig d+                  nd <- M.mctxNameDisp <$> getFocusedEnv+                  let doc = fixNameDisp nd (pp texpr)+                  void (qcExpr qcMode doc texpr schema) -qcCmd qcMode str =-  do expr <- replParseExpr str-     (val,ty) <- replEvalExpr expr+qcCmd qcMode str pos fnm =+  do expr <- replParseExpr str pos fnm+     (_,texpr,schema) <- replCheckExpr expr+     nd <- M.mctxNameDisp <$> getFocusedEnv+     let doc = fixNameDisp nd (ppPrec 3 expr) -- function application has precedence 3+     void (qcExpr qcMode doc texpr schema)+++data TestReport = TestReport+  { reportExpr :: Doc+  , reportResult :: TestResult+  , reportTestsRun :: Integer+  , reportTestsPossible :: Maybe Integer+  }++qcExpr ::+  QCMode ->+  Doc ->+  T.Expr ->+  T.Schema ->+  REPL TestReport+qcExpr qcMode exprDoc texpr schema =+  do (val,ty) <- replEvalCheckedExpr texpr schema      testNum <- (toInteger :: Int -> Integer) <$> getKnownUser "tests"      tenv <- E.envTypes . M.deEnv <$> getDynEnv      let tyv = E.evalValType tenv ty      percentRef <- io $ newIORef Nothing      testsRef <- io $ newIORef 0+      case testableType tyv of        Just (Just sz,tys,vss,_gens) | qcMode == QCExhaust || sz <= testNum -> do             rPutStrLn "Using exhaustive testing."@@ -440,15 +441,15 @@                                             val vss)                          (\ex -> do rPutStrLn "\nTest interrupted..."                                     num <- io $ readIORef testsRef-                                    let report = TestReport Pass str num (Just sz)-                                    ppReport (map E.tValTy tys) expr False report+                                    let report = TestReport exprDoc Pass num (Just sz)+                                    ppReport tys False report                                     rPutStrLn $ interruptedExhaust num sz                                     Ex.throwM (ex :: Ex.SomeException))-            let report = TestReport res str num (Just sz)+            let report = TestReport exprDoc res num (Just sz)             delProgress             delTesting-            ppReport (map E.tValTy tys) expr True report-            return [report]+            ppReport tys True report+            return report         Just (sz,tys,_,gens) | qcMode == QCRandom -> do             rPutStrLn "Using random testing."@@ -459,20 +460,20 @@                                         testNum val gens g)                          (\ex -> do rPutStrLn "\nTest interrupted..."                                     num <- io $ readIORef testsRef-                                    let report = TestReport Pass str num sz-                                    ppReport (map E.tValTy tys) expr False report+                                    let report = TestReport exprDoc Pass num sz+                                    ppReport tys False report                                     case sz of                                       Just n -> rPutStrLn $ coverageString num n                                       _ -> return ()                                     Ex.throwM (ex :: Ex.SomeException))-            let report = TestReport res str num sz+            let report = TestReport exprDoc res num sz             delProgress             delTesting-            ppReport (map E.tValTy tys) expr False report+            ppReport tys False report             case sz of               Just n | isPass res -> rPutStrLn $ coverageString testNum n               _ -> return ()-            return [report]+            return report        _ -> raise (TypeNotTestable ty)    where@@ -502,7 +503,6 @@        ++ showValNum        ++ " values)" -   totProgressWidth = 4    -- 100%    lg2 :: Integer -> Integer@@ -512,7 +512,6 @@                          in round $ logBase 2 valNumD :: Integer    prt msg   = rPutStr msg >> io (hFlush stdout)-  prtLn msg = rPutStrLn msg >> io (hFlush stdout)    ppProgress percentRef testsRef this tot =     do io $ writeIORef testsRef this@@ -536,34 +535,45 @@   delTesting  = del (length testingMsg)   delProgress = del totProgressWidth -  ppReport _tys _expr isExhaustive (TestReport Pass _str testNum _testPossible) =-    do prtLn $ "Passed " ++ show testNum ++ " tests."++ppReport :: [E.TValue] -> Bool -> TestReport -> REPL ()+ppReport _tys isExhaustive (TestReport _exprDoc Pass testNum _testPossible) =+    do rPutStrLn ("Passed " ++ show testNum ++ " tests.")        when isExhaustive (rPutStrLn "Q.E.D.")-  ppReport tys expr _ (TestReport failure _str _testNum _testPossible) =-    ppFailure tys expr failure+ppReport tys _ (TestReport exprDoc failure _testNum _testPossible) =+    do ppFailure tys exprDoc failure -  ppFailure tys pexpr failure = do-    opts <- getPPValOpts-    case failure of-      FailFalse vs -> do-        printCounterexample PredicateFalsified pexpr vs-        case (tys,vs) of-          ([t],[v]) -> bindItVariableVal t v-          _ -> let fs = [ M.packIdent ("arg" ++ show (i::Int)) | i <- [ 1 .. ] ]-                   t = T.TRec (recordFromFields (zip fs tys))-                   v = E.VRecord (recordFromFields (zip fs (map return vs)))-               in bindItVariableVal t v+ppFailure :: [E.TValue] -> Doc -> TestResult -> REPL ()+ppFailure tys exprDoc failure = do+    ~(EnvBool showEx) <- getUser "showExamples" -      FailError err [] -> do-        prtLn "ERROR"-        rPrint (pp err)-      FailError err vs -> do-        prtLn "ERROR for the following inputs:"-        mapM_ (\v -> rPrint =<< (rEval $ E.ppValue Concrete opts v)) vs-        rPrint (pp err)-      Pass -> panic "Cryptol.REPL.Command" ["unexpected Test.Pass"]+    vs <- case failure of+            FailFalse vs ->+              do rPutStrLn "Counterexample"+                 when showEx (printCounterexample PredicateFalsified exprDoc vs)+                 pure vs+            FailError err vs+              | null vs || not showEx ->+                do rPutStrLn "ERROR"+                   rPrint (pp err)+                   pure vs+              | otherwise ->+                do rPutStrLn "ERROR for the following inputs:"+                   printCounterexample SafetyViolation exprDoc vs+                   rPrint (pp err)+                   pure vs +            Pass -> panic "Cryptol.REPL.Command" ["unexpected Test.Pass"] +    -- bind the 'it' variable+    case (tys,vs) of+      ([t],[v]) -> bindItVariableVal t v+      _ -> let fs = [ M.packIdent ("arg" ++ show (i::Int)) | i <- [ 1 .. ] ]+               t = E.TVRec (recordFromFields (zip fs tys))+               v = E.VRecord (recordFromFields (zip fs (map return vs)))+           in bindItVariableVal t v++ -- | This function computes the expected coverage percentage and -- expected number of unique test vectors when using random testing. --@@ -606,7 +616,7 @@     proportion = negate (expm1 (numD * log1p (negate (recip szD)))) -satCmd, proveCmd :: String -> REPL ()+satCmd, proveCmd :: String -> (Int,Int) -> Maybe FilePath -> REPL () satCmd = cmdProveSat True proveCmd = cmdProveSat False @@ -628,16 +638,22 @@       ]  -- | Attempts to prove the given term is safe for all inputs-safeCmd :: String -> REPL ()-safeCmd str = do+safeCmd :: String -> (Int,Int) -> Maybe FilePath -> REPL ()+safeCmd str pos fnm = do   proverName <- getKnownUser "prover"-  fileName   <- getKnownUser "smtfile"+  fileName   <- getKnownUser "smtFile"   let mfile = if fileName == "-" then Nothing else Just fileName+  pexpr <- replParseExpr str pos fnm+  nd <- M.mctxNameDisp <$> getFocusedEnv+  let exprDoc = fixNameDisp nd (ppPrec 3 pexpr) -- function application has precedence 3 +  let rng = fromMaybe (mkInteractiveRange pos fnm) (getLoc pexpr)+  (_,texpr,schema) <- replCheckExpr pexpr+   if proverName `elem` ["offline","sbv-offline","w4-offline"] then-    offlineProveSat proverName SafetyQuery str mfile+    offlineProveSat proverName SafetyQuery texpr schema mfile   else-     do (firstProver,result,stats) <- rethrowErrorCall (onlineProveSat proverName SafetyQuery str mfile)+     do (firstProver,result,stats) <- rethrowErrorCall (onlineProveSat proverName SafetyQuery texpr schema mfile)         case result of           EmptyResult         ->             panic "REPL.Command" [ "got EmptyResult for online prover query" ]@@ -651,11 +667,11 @@             let tes = map ( \(t,e,_) -> (t,e)) tevs                 vs  = map ( \(_,_,v) -> v)     tevs -            (t,e) <- mkSolverResult "counterexample" False (Right tes)-            pexpr <- replParseExpr str+            (t,e) <- mkSolverResult "counterexample" rng False (Right tes) -            ~(EnvBool yes) <- getUser "show-examples"-            when yes $ printCounterexample cexType pexpr vs+            ~(EnvBool yes) <- getUser "showExamples"+            when yes $ printCounterexample cexType exprDoc vs+            when yes $ printSafetyViolation texpr schema vs              void $ bindItVariable t e @@ -670,30 +686,50 @@ -- console, and binds the @it@ variable to a record whose form depends -- on the expression given. See ticket #66 for a discussion of this -- design.-cmdProveSat :: Bool -> String -> REPL ()-cmdProveSat isSat "" =+cmdProveSat :: Bool -> String -> (Int,Int) -> Maybe FilePath -> REPL ()+cmdProveSat isSat "" _pos _fnm =   do (xs,disp) <- getPropertyNames      let nameStr x = show (fixNameDisp disp (pp x))      if null xs         then rPutStrLn "There are no properties in scope."-        else forM_ xs $ \x ->+        else forM_ xs $ \(x,d) ->                do let str = nameStr x                   if isSat                      then rPutStr $ ":sat "   ++ str ++ "\n\t"                      else rPutStr $ ":prove " ++ str ++ "\n\t"-                  cmdProveSat isSat str-cmdProveSat isSat str = do+                  let texpr = T.EVar x+                  let schema = M.ifDeclSig d+                  nd <- M.mctxNameDisp <$> getFocusedEnv+                  let doc = fixNameDisp nd (pp texpr)+                  proveSatExpr isSat (M.nameLoc x) doc texpr schema++cmdProveSat isSat str pos fnm = do+  pexpr <- replParseExpr str pos fnm+  nd <- M.mctxNameDisp <$> getFocusedEnv+  let doc = fixNameDisp nd (ppPrec 3 pexpr) -- function application has precedence 3+  (_,texpr,schema) <- replCheckExpr pexpr+  let rng = fromMaybe (mkInteractiveRange pos fnm) (getLoc pexpr)+  proveSatExpr isSat rng doc texpr schema++proveSatExpr ::+  Bool ->+  Range ->+  Doc ->+  T.Expr ->+  T.Schema ->+  REPL ()+proveSatExpr isSat rng exprDoc texpr schema = do   let cexStr | isSat = "satisfying assignment"              | otherwise = "counterexample"   qtype <- if isSat then SatQuery <$> getUserSatNum else pure ProveQuery   proverName <- getKnownUser "prover"-  fileName   <- getKnownUser "smtfile"+  fileName   <- getKnownUser "smtFile"   let mfile = if fileName == "-" then Nothing else Just fileName    if proverName `elem` ["offline","sbv-offline","w4-offline"] then-     offlineProveSat proverName qtype str mfile+     offlineProveSat proverName qtype texpr schema mfile   else-     do (firstProver,result,stats) <- rethrowErrorCall (onlineProveSat proverName qtype str mfile)+     do (firstProver,result,stats) <- rethrowErrorCall (onlineProveSat proverName qtype texpr schema mfile)         case result of           EmptyResult         ->             panic "REPL.Command" [ "got EmptyResult for online prover query" ]@@ -702,7 +738,7 @@            ThmResult ts        -> do             rPutStrLn (if isSat then "Unsatisfiable" else "Q.E.D.")-            (t, e) <- mkSolverResult cexStr (not isSat) (Left ts)+            (t, e) <- mkSolverResult cexStr rng (not isSat) (Left ts)             void $ bindItVariable t e            CounterExample cexType tevs -> do@@ -710,19 +746,24 @@             let tes = map ( \(t,e,_) -> (t,e)) tevs                 vs  = map ( \(_,_,v) -> v)     tevs -            (t,e) <- mkSolverResult cexStr isSat (Right tes)-            pexpr <- replParseExpr str+            (t,e) <- mkSolverResult cexStr rng isSat (Right tes) -            ~(EnvBool yes) <- getUser "show-examples"-            when yes $ printCounterexample cexType pexpr vs+            ~(EnvBool yes) <- getUser "showExamples"+            when yes $ printCounterexample cexType exprDoc vs +            -- if there's a safety violation, evalute the counterexample to+            -- find and print the actual concrete error+            case cexType of+              SafetyViolation -> when yes $ printSafetyViolation texpr schema vs+              _ -> return ()+             void $ bindItVariable t e            AllSatResult tevss -> do             rPutStrLn "Satisfiable"             let tess = map (map $ \(t,e,_) -> (t,e)) tevss                 vss  = map (map $ \(_,_,v) -> v)     tevss-            resultRecs <- mapM (mkSolverResult cexStr isSat . Right) tess+            resultRecs <- mapM (mkSolverResult cexStr rng isSat . Right) tess             let collectTes tes = (t, es)                   where                     (ts, es) = unzip tes@@ -736,32 +777,42 @@                             [ "no satisfying assignments after mkSolverResult" ]                     [(t, e)] -> (t, [e])                     _        -> collectTes resultRecs-            pexpr <- replParseExpr str -            ~(EnvBool yes) <- getUser "show-examples"-            when yes $ forM_ vss (printSatisfyingModel pexpr)+            ~(EnvBool yes) <- getUser "showExamples"+            when yes $ forM_ vss (printSatisfyingModel exprDoc) -            case (ty, exprs) of-              (t, [e]) -> void $ bindItVariable t e-              (t, es ) -> bindItVariables t es+            case exprs of+              [e] -> void $ bindItVariable ty e+              _   -> bindItVariables ty exprs          seeStats <- getUserShowProverStats         when seeStats (showProverStats firstProver stats) -onlineProveSat :: String-               -> QueryType-               -> String -> Maybe FilePath-               -> REPL (Maybe String,ProverResult,ProverStats)-onlineProveSat proverName qtype str mfile = do++printSafetyViolation :: T.Expr -> T.Schema -> [E.GenValue Concrete] -> REPL ()+printSafetyViolation texpr schema vs =+    catch+      (do (fn,_) <- replEvalCheckedExpr texpr schema+          rEval (E.forceValue =<< foldM (\f v -> E.fromVFun Concrete f (pure v)) fn vs))+      (\case+          EvalError eex -> rPutStrLn (show (pp eex))+          ex -> raise ex)++onlineProveSat ::+  String ->+  QueryType ->+  T.Expr ->+  T.Schema ->+  Maybe FilePath ->+  REPL (Maybe String,ProverResult,ProverStats)+onlineProveSat proverName qtype expr schema mfile = do   verbose <- getKnownUser "debug"   modelValidate <- getUserProverValidate-  parseExpr <- replParseExpr str-  (_, expr, schema) <- replCheckExpr parseExpr   validEvalContext expr   validEvalContext schema   decls <- fmap M.deDecls getDynEnv   timing <- io (newIORef 0)-  ~(EnvBool ignoreSafety) <- getUser "ignore-safety"+  ~(EnvBool ignoreSafety) <- getUser "ignoreSafety"   let cmd = ProverCommand {           pcQueryType    = qtype         , pcProverName   = proverName@@ -777,22 +828,21 @@   (firstProver, res) <- getProverConfig >>= \case        Left sbvCfg -> liftModuleCmd $ SBV.satProve sbvCfg cmd        Right w4Cfg ->-         do ~(EnvBool hashConsing) <- getUser "hash-consing"+         do ~(EnvBool hashConsing) <- getUser "hashConsing"             ~(EnvBool warnUninterp) <- getUser "warnUninterp"             liftModuleCmd $ W4.satProve w4Cfg hashConsing warnUninterp cmd    stas <- io (readIORef timing)   return (firstProver,res,stas) -offlineProveSat :: String -> QueryType -> String -> Maybe FilePath -> REPL ()-offlineProveSat proverName qtype str mfile = do+offlineProveSat :: String -> QueryType -> T.Expr -> T.Schema -> Maybe FilePath -> REPL ()+offlineProveSat proverName qtype expr schema mfile = do   verbose <- getKnownUser "debug"   modelValidate <- getUserProverValidate-  parseExpr <- replParseExpr str-  (_, expr, schema) <- replCheckExpr parseExpr+   decls <- fmap M.deDecls getDynEnv   timing <- io (newIORef 0)-  ~(EnvBool ignoreSafety) <- getUser "ignore-safety"+  ~(EnvBool ignoreSafety) <- getUser "ignoreSafety"   let cmd = ProverCommand {           pcQueryType    = qtype         , pcProverName   = proverName@@ -832,7 +882,7 @@                Nothing -> rPutStr smtlib      Right w4Cfg ->-      do ~(EnvBool hashConsing) <- getUser "hash-consing"+      do ~(EnvBool hashConsing) <- getUser "hashConsing"          ~(EnvBool warnUninterp) <- getUser "warnUninterp"          result <- liftModuleCmd $ W4.satProveOffline w4Cfg hashConsing warnUninterp cmd $ \f ->                      do displayMsg@@ -855,13 +905,15 @@  -- | Make a type/expression pair that is suitable for binding to @it@ -- after running @:sat@ or @:prove@-mkSolverResult :: String-               -> Bool-               -> Either [T.Type] [(T.Type, T.Expr)]-               -> REPL (T.Type, T.Expr)-mkSolverResult thing result earg =+mkSolverResult ::+  String ->+  Range ->+  Bool ->+  Either [E.TValue] [(E.TValue, T.Expr)] ->+  REPL (E.TValue, T.Expr)+mkSolverResult thing rng result earg =   do prims <- getPrimMap-     let addError t = (t, T.eError prims t ("no " ++ thing ++ " available"))+     let addError t = (t, T.ELocated rng (T.eError prims (E.tValTy t) ("no " ++ thing ++ " available")))           argF = case earg of                   Left ts   -> mkArgs (map addError ts)@@ -871,7 +923,7 @@          eFalse = T.ePrim prims (M.prelPrim "False")          resultE = if result then eTrue else eFalse -         rty = T.TRec (recordFromFields $ [(rIdent, T.tBit )] ++ map fst argF)+         rty = E.TVRec (recordFromFields $ [(rIdent, E.TVBit)] ++ map fst argF)          re  = T.ERec (recordFromFields $ [(rIdent, resultE)] ++ map snd argF)       return (rty, re)@@ -882,9 +934,9 @@       let argName = M.packIdent ("arg" ++ show n)        in ((argName,t),(argName,e)) -specializeCmd :: String -> REPL ()-specializeCmd str = do-  parseExpr <- replParseExpr str+specializeCmd :: String -> (Int,Int) -> Maybe FilePath -> REPL ()+specializeCmd str pos fnm = do+  parseExpr <- replParseExpr str pos fnm   (_, expr, schema) <- replCheckExpr parseExpr   spexpr <- replSpecExpr expr   rPutStrLn  "Expression type:"@@ -894,9 +946,9 @@   rPutStrLn  "Specialized expression:"   rPutStrLn $ dump spexpr -refEvalCmd :: String -> REPL ()-refEvalCmd str = do-  parseExpr <- replParseExpr str+refEvalCmd :: String -> (Int,Int) -> Maybe FilePath -> REPL ()+refEvalCmd str pos fnm = do+  parseExpr <- replParseExpr str pos fnm   (_, expr, schema) <- replCheckExpr parseExpr   validEvalContext expr   validEvalContext schema@@ -904,9 +956,9 @@   opts <- getPPValOpts   rPrint $ R.ppEValue opts val -astOfCmd :: String -> REPL ()-astOfCmd str = do- expr <- replParseExpr str+astOfCmd :: String -> (Int,Int) -> Maybe FilePath -> REPL ()+astOfCmd str pos fnm = do+ expr <- replParseExpr str pos fnm  (re,_,_) <- replCheckExpr (P.noPos expr)  rPrint (fmap M.nameUnique re) @@ -915,10 +967,10 @@   me <- getModuleEnv   rPrint $ T.showParseable $ concatMap T.mDecls $ M.loadedModules me -typeOfCmd :: String -> REPL ()-typeOfCmd str = do+typeOfCmd :: String -> (Int,Int) -> Maybe FilePath -> REPL ()+typeOfCmd str pos fnm = do -  expr         <- replParseExpr str+  expr         <- replParseExpr str pos fnm   (_re,def,sig) <- replCheckExpr expr    -- XXX need more warnings from the module system@@ -942,7 +994,7 @@          let t = T.tWord (T.tNum (toInteger len * 8))          let x = T.EProofApp (T.ETApp (T.ETApp number (T.tNum val)) t)          let expr = T.EApp f x-         void $ bindItVariable (T.tString len) expr+         void $ bindItVariable (E.TVSeq (toInteger len) (E.TVSeq 8 E.TVBit)) expr  -- | Convert a 'ByteString' (big-endian) of length @n@ to an 'Integer' -- with @8*n@ bits. This function uses a balanced binary fold to@@ -963,9 +1015,9 @@     x1 = byteStringToInteger bs1     x2 = byteStringToInteger bs2 -writeFileCmd :: FilePath -> String -> REPL ()-writeFileCmd file str = do-  expr         <- replParseExpr str+writeFileCmd :: FilePath -> String -> (Int,Int) -> Maybe FilePath -> REPL ()+writeFileCmd file str pos fnm = do+  expr         <- replParseExpr str pos fnm   (val,ty)     <- replEvalExpr expr   if not (tIsByteSeq ty)    then rPrint $  "Cannot write expression of types other than [n][8]."@@ -990,10 +1042,10 @@   rEval :: E.Eval a -> REPL a-rEval m = io (E.runEval m)+rEval m = io (E.runEval mempty m)  rEvalRethrow :: E.Eval a -> REPL a-rEvalRethrow m = io $ rethrowEvalError $ E.runEval m+rEvalRethrow m = io $ rethrowEvalError $ E.runEval mempty m  reloadCmd :: REPL () reloadCmd  = do@@ -1348,9 +1400,9 @@   | null cmd  = mapM_ rPutStrLn (genHelp commandList)   | cmd0 : args <- words cmd, ":" `isPrefixOf` cmd0 =     case findCommandExact cmd0 of-      []  -> void $ runCommand (Unknown cmd0)+      []  -> void $ runCommand 1 Nothing (Unknown cmd0)       [c] -> showCmdHelp c args-      cs  -> void $ runCommand (Ambiguous cmd0 (concatMap cNames cs))+      cs  -> void $ runCommand 1 Nothing (Ambiguous cmd0 (concatMap cNames cs))   | otherwise =     case parseHelpName cmd of       Just qname ->@@ -1557,12 +1609,34 @@   Right a -> return a   Left e  -> raise (ParseError e) -replParseInput :: String -> REPL (P.ReplInput P.PName)-replParseInput = replParse (parseReplWith interactiveConfig . T.pack)+replParseInput :: String -> Int -> Maybe FilePath -> REPL (P.ReplInput P.PName)+replParseInput str lineNum fnm = replParse (parseReplWith cfg . T.pack) str+  where+  cfg = case fnm of+          Nothing -> interactiveConfig{ cfgStart = Position lineNum 1 }+          Just f  -> defaultConfig+                     { cfgSource = f+                     , cfgStart  = Position lineNum 1+                     } -replParseExpr :: String -> REPL (P.Expr P.PName)-replParseExpr = replParse (parseExprWith interactiveConfig . T.pack)+replParseExpr :: String -> (Int,Int) -> Maybe FilePath -> REPL (P.Expr P.PName)+replParseExpr str (l,c) fnm = replParse (parseExprWith cfg. T.pack) str+  where+  cfg = case fnm of+          Nothing -> interactiveConfig{ cfgStart = Position l c }+          Just f  -> defaultConfig+                     { cfgSource = f+                     , cfgStart  = Position l c+                     } +mkInteractiveRange :: (Int,Int) -> Maybe FilePath -> Range+mkInteractiveRange (l,c) mb = Range p p src+  where+  p = Position l c+  src = case mb of+          Nothing -> "<interactive>"+          Just b  -> b+ interactiveConfig :: Config interactiveConfig = defaultConfig { cfgSource = "<interactive>" } @@ -1571,9 +1645,19 @@  liftModuleCmd :: M.ModuleCmd a -> REPL a liftModuleCmd cmd =-  do evo <- getEvalOpts+  do evo <- getEvalOptsAction      env <- getModuleEnv-     moduleCmdResult =<< io (cmd (evo, BS.readFile, env))+     callStacks <- getCallStacks+     let cfg = M.meSolverConfig env+     let minp s =+             M.ModuleInput+                { minpCallStacks = callStacks+                , minpEvalOpts   = evo+                , minpByteReader = BS.readFile+                , minpModuleEnv  = env+                , minpTCSolver   = s+                }+     moduleCmdResult =<< io (SMT.withSolver cfg (cmd . minp))  moduleCmdResult :: M.ModuleRes a -> REPL a moduleCmdResult (res,ws0) = do@@ -1644,8 +1728,13 @@ replEvalExpr :: P.Expr P.PName -> REPL (Concrete.Value, T.Type) replEvalExpr expr =   do (_,def,sig) <- replCheckExpr expr-     validEvalContext def+     replEvalCheckedExpr def sig++replEvalCheckedExpr :: T.Expr -> T.Schema -> REPL (Concrete.Value, T.Type)+replEvalCheckedExpr def sig =+  do validEvalContext def      validEvalContext sig+      me <- getModuleEnv      let cfg = M.meSolverConfig me      mbDef <- io $ SMT.withSolver cfg (\s -> defaultReplExpr s def sig)@@ -1658,12 +1747,20 @@                let su = T.listParamSubst tys                return (def1, T.apSubst su (T.sType sig)) +     whenDebug (rPutStrLn (dump def1))++     tenv <- E.envTypes . M.deEnv <$> getDynEnv+     let tyv = E.evalValType tenv ty+      -- add "it" to the namespace via a new declaration-     itVar <- bindItVariable ty def1+     itVar <- bindItVariable tyv def1 +     let itExpr = case getLoc def of+                    Nothing  -> T.EVar itVar+                    Just rng -> T.ELocated rng (T.EVar itVar)+      -- evaluate the it variable-     val <- liftModuleCmd (rethrowEvalError . M.evalExpr (T.EVar itVar))-     whenDebug (rPutStrLn (dump def1))+     val <- liftModuleCmd (rethrowEvalError . M.evalExpr itExpr)      return (val,ty)   where   warnDefaults ts =@@ -1692,12 +1789,12 @@ -- | Creates a fresh binding of "it" to the expression given, and adds -- it to the current dynamic environment.  The fresh name generated -- is returned.-bindItVariable :: T.Type -> T.Expr -> REPL T.Name+bindItVariable :: E.TValue -> T.Expr -> REPL T.Name bindItVariable ty expr = do   freshIt <- freshName itIdent M.UserName   let schema = T.Forall { T.sVars  = []                         , T.sProps = []-                        , T.sType  = ty+                        , T.sType  = E.tValTy ty                         }       decl = T.Decl { T.dName       = freshIt                     , T.dSignature  = schema@@ -1718,7 +1815,7 @@ -- | Extend the dynamic environment with a fresh binding for "it", -- as defined by the given value.  If we cannot determine the definition -- of the value, then we don't bind `it`.-bindItVariableVal :: T.Type -> Concrete.Value -> REPL ()+bindItVariableVal :: E.TValue -> Concrete.Value -> REPL () bindItVariableVal ty val =   do prims   <- getPrimMap      mb      <- rEval (Concrete.toExpr prims ty val)@@ -1730,12 +1827,12 @@ -- | Creates a fresh binding of "it" to a finite sequence of -- expressions of the same type, and adds that sequence to the current -- dynamic environment-bindItVariables :: T.Type -> [T.Expr] -> REPL ()+bindItVariables :: E.TValue -> [T.Expr] -> REPL () bindItVariables ty exprs = void $ bindItVariable seqTy seqExpr   where     len = length exprs-    seqTy = T.tSeq (T.tNum len) ty-    seqExpr = T.EList exprs ty+    seqTy = E.TVSeq (toInteger len) ty+    seqExpr = T.EList exprs (E.tValTy ty)  replEvalDecl :: P.Decl P.PName -> REPL () replEvalDecl decl = do@@ -1770,19 +1867,26 @@ trim = sanitizeEnd . sanitize  -- | Split at the first word boundary.-splitCommand :: String -> Maybe (String,String)-splitCommand txt =-  case sanitize txt of-    ':' : more+splitCommand :: String -> Maybe (Int,String,String)+splitCommand = go 0+  where+   go !len (c  : more)+      | isSpace c = go (len+1) more++   go !len (':': more)       | (as,bs) <- span (\x -> isPunctuation x || isSymbol x) more-      , not (null as) -> Just (':' : as, sanitize bs)+      , (ws,cs) <- span isSpace bs+      , not (null as) = Just (len+1+length as+length ws, ':' : as, cs)        | (as,bs) <- break isSpace more-      , not (null as) -> Just (':' : as, sanitize bs)+      , (ws,cs) <- span isSpace bs+      , not (null as) = Just (len+1+length as+length ws, ':' : as, cs) -      | otherwise -> Nothing+      | otherwise = Nothing -    expr -> guard (not (null expr)) >> return (expr,[])+   go !len expr+      | null expr = Nothing+      | otherwise = Just (len+length expr, expr, [])  -- | Uncons a list. uncons :: [a] -> Maybe (a,[a])@@ -1807,23 +1911,24 @@ -- | Parse a line as a command. parseCommand :: (String -> [CommandDescr]) -> String -> Maybe Command parseCommand findCmd line = do-  (cmd,args) <- splitCommand line+  (cmdLen,cmd,args) <- splitCommand line   let args' = sanitizeEnd args   case findCmd cmd of     [c] -> case cBody c of-      ExprArg     body -> Just (Command (body args'))-      DeclsArg    body -> Just (Command (body args'))-      ExprTypeArg body -> Just (Command (body args'))-      ModNameArg  body -> Just (Command (body args'))-      FilenameArg body -> Just (Command (body =<< expandHome args'))-      OptionArg   body -> Just (Command (body args'))-      ShellArg    body -> Just (Command (body args'))-      HelpArg     body -> Just (Command (body args'))-      NoArg       body -> Just (Command  body)+      ExprArg     body -> Just (Command \l fp -> (body args' (l,cmdLen+1) fp))+      DeclsArg    body -> Just (Command \_ _ -> (body args'))+      ExprTypeArg body -> Just (Command \_ _ -> (body args'))+      ModNameArg  body -> Just (Command \_ _ -> (body args'))+      FilenameArg body -> Just (Command \_ _ -> (body =<< expandHome args'))+      OptionArg   body -> Just (Command \_ _ -> (body args'))+      ShellArg    body -> Just (Command \_ _ -> (body args'))+      HelpArg     body -> Just (Command \_ _ -> (body args'))+      NoArg       body -> Just (Command \_ _ -> body)       FileExprArg body ->-        case extractFilePath args' of-           Just (fp,expr) -> Just (Command (expandHome fp >>= flip body expr))-           Nothing        -> Nothing+           do (fpLen,fp,expr) <- extractFilePath args'+              Just (Command \l fp' -> do let col = cmdLen + fpLen + 1+                                         hm <- expandHome fp+                                         body hm expr (l,col) fp')     [] -> case uncons cmd of       Just (':',_) -> Just (Unknown cmd)       Just _       -> Just (Command (evalCmd line))@@ -1839,9 +1944,10 @@       _ -> return path    extractFilePath ipt =-    let quoted q = (\(a,b) -> (a, drop 1 b)) . break (== q)+    let quoted q = (\(a,b) -> (length a + 2, a, drop 1 b)) . break (== q)     in case ipt of         ""        -> Nothing         '\'':rest -> Just $ quoted '\'' rest         '"':rest  -> Just $ quoted '"' rest-        _         -> Just $ break isSpace ipt+        _         -> let (a,b) = break isSpace ipt in+                     if null a then Nothing else Just (length a, a, b)
src/Cryptol/REPL/Monad.hs view
@@ -35,8 +35,11 @@   , getFocusedEnv   , getModuleEnv, setModuleEnv   , getDynEnv, setDynEnv+  , getCallStacks   , uniqify, freshName   , whenDebug+  , getEvalOptsAction+  , getPPValOpts   , getExprNames   , getTypeNames   , getPropertyNames@@ -57,6 +60,7 @@   , OptionDescr(..)   , setUser, getUser, getKnownUser, tryGetUser   , userOptions+  , userOptionsWithAliases   , getUserSatNum   , getUserShowProverStats   , getUserProverValidate@@ -76,7 +80,7 @@  import Cryptol.REPL.Trie -import Cryptol.Eval (EvalError, Unsupported)+import Cryptol.Eval (EvalErrorEx, Unsupported, WordTooWide,EvalOpts(..)) import qualified Cryptol.ModuleSystem as M import qualified Cryptol.ModuleSystem.Env as M import qualified Cryptol.ModuleSystem.Name as M@@ -96,7 +100,6 @@ import Cryptol.Symbolic (SatNum(..)) import Cryptol.Symbolic.SBV (SBVPortfolioException) import Cryptol.Symbolic.What4 (W4Exception)-import Cryptol.Backend.Monad(PPFloatFormat(..),PPFloatExp(..)) import qualified Cryptol.Symbolic.SBV as SBV (proverNames, setupProver, defaultProver, SBVProverConfig) import qualified Cryptol.Symbolic.What4 as W4 (proverNames, setupProver, W4ProverConfig) @@ -155,6 +158,8 @@   , eLogger      :: Logger     -- ^ Use this to send messages to the user +  , eCallStacks :: Bool+   , eUpdateTitle :: REPL ()     -- ^ Execute this every time we load a module.     -- This is used to change the title of terminal when loading a module.@@ -163,8 +168,8 @@   }  -- | Initial, empty environment.-defaultRW :: Bool -> Logger -> IO RW-defaultRW isBatch l = do+defaultRW :: Bool -> Bool ->Logger -> IO RW+defaultRW isBatch callStacks l = do   env <- M.initialModuleEnv   return RW     { eLoadedMod   = Nothing@@ -174,6 +179,7 @@     , eModuleEnv   = env     , eUserEnv     = mkUserEnv userOptions     , eLogger      = l+    , eCallStacks  = callStacks     , eUpdateTitle = return ()     , eProverConfig = Left SBV.defaultProver     }@@ -220,9 +226,9 @@ newtype REPL a = REPL { unREPL :: IORef RW -> IO a }  -- | Run a REPL action with a fresh environment.-runREPL :: Bool -> Logger -> REPL a -> IO a-runREPL isBatch l m = do-  ref <- newIORef =<< defaultRW isBatch l+runREPL :: Bool -> Bool -> Logger -> REPL a -> IO a+runREPL isBatch callStacks l m = do+  ref <- newIORef =<< defaultRW isBatch callStacks l   unREPL m ref  instance Functor REPL where@@ -289,7 +295,8 @@   | DirectoryNotFound FilePath   | NoPatError [Error]   | NoIncludeError [IncludeError]-  | EvalError EvalError+  | EvalError EvalErrorEx+  | TooWide WordTooWide   | Unsupported Unsupported   | ModuleSystemError NameDisp M.ModuleError   | EvalPolyError T.Schema@@ -319,6 +326,7 @@     ModuleSystemError ns me -> fixNameDisp ns (pp me)     EvalError e          -> pp e     Unsupported e        -> pp e+    TooWide e            -> pp e     EvalPolyError s      -> text "Cannot evaluate polymorphic value."                          $$ text "Type:" <+> pp s     TypeNotTestable t    -> text "The expression is not of a testable type."@@ -344,15 +352,21 @@   rethrowEvalError :: IO a -> IO a-rethrowEvalError m = run `X.catch` rethrow `X.catch` rethrowUnsupported+rethrowEvalError m =+    run `X.catch` rethrow+        `X.catch` rethrowTooWide+        `X.catch` rethrowUnsupported   where   run = do     a <- m     return $! a -  rethrow :: EvalError -> IO a+  rethrow :: EvalErrorEx -> IO a   rethrow exn = X.throwIO (EvalError exn) +  rethrowTooWide :: WordTooWide -> IO a+  rethrowTooWide exn = X.throwIO (TooWide exn)+   rethrowUnsupported :: Unsupported -> IO a   rethrowUnsupported exn = X.throwIO (Unsupported exn) @@ -376,6 +390,36 @@ getPrompt :: REPL String getPrompt  = mkPrompt `fmap` getRW +getCallStacks :: REPL Bool+getCallStacks = eCallStacks <$> getRW++-- Get the setting we should use for displaying values.+getPPValOpts :: REPL PPOpts+getPPValOpts =+  do base      <- getKnownUser "base"+     ascii     <- getKnownUser "ascii"+     infLength <- getKnownUser "infLength"++     fpBase    <- getKnownUser "fpBase"+     fpFmtTxt  <- getKnownUser "fpFormat"+     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+                   }++getEvalOptsAction :: REPL (IO EvalOpts)+getEvalOptsAction = REPL $ \rwRef -> pure $+  do ppOpts <- unREPL getPPValOpts rwRef+     l      <- unREPL getLogger rwRef+     return EvalOpts { evalPPOpts = ppOpts, evalLogger = l }+ clearLoadedMod :: REPL () clearLoadedMod = do modifyRW_ (\rw -> rw { eLoadedMod = upd <$> eLoadedMod rw })                     updateREPLTitle@@ -513,12 +557,12 @@      return (map (show . pp) (Map.keys (M.neTypes fNames)))  -- | Return a list of property names, sorted by position in the file.-getPropertyNames :: REPL ([M.Name],NameDisp)+getPropertyNames :: REPL ([(M.Name,M.IfaceDecl)],NameDisp) getPropertyNames =   do fe <- getFocusedEnv      let xs = M.ifDecls (M.mctxDecls fe)-         ps = sortBy (comparing (from . M.nameLoc))-              [ x | (x,d) <- Map.toList xs,+         ps = sortBy (comparing (from . M.nameLoc . fst))+              [ (x,d) | (x,d) <- Map.toList xs,                     T.PragmaProperty `elem` M.ifDeclPragmas d ]       return (ps, M.mctxNameDisp fe)@@ -594,7 +638,7 @@  -- | Set a user option. setUser :: String -> String -> REPL ()-setUser name val = case lookupTrieExact name userOptions of+setUser name val = case lookupTrieExact name userOptionsWithAliases of    [opt] -> setUserOpt opt   []    -> rPutStrLn ("Unknown env value `" ++ name ++ "`")@@ -697,10 +741,10 @@   getUserShowProverStats :: REPL Bool-getUserShowProverStats = getKnownUser "prover-stats"+getUserShowProverStats = getKnownUser "proverStats"  getUserProverValidate :: REPL Bool-getUserProverValidate = getKnownUser "prover-validate"+getUserProverValidate = getKnownUser "proverValidate"  -- Environment Options --------------------------------------------------------- @@ -722,47 +766,53 @@  data OptionDescr = OptionDescr   { optName    :: String+  , optAliases :: [String]   , optDefault :: EnvVal   , optCheck   :: Checker   , optHelp    :: String   , optEff     :: EnvVal -> REPL ()   } -simpleOpt :: String -> EnvVal -> Checker -> String -> OptionDescr-simpleOpt optName optDefault optCheck optHelp =+simpleOpt :: String -> [String] -> EnvVal -> Checker -> String -> OptionDescr+simpleOpt optName optAliases optDefault optCheck optHelp =   OptionDescr { optEff = \ _ -> return (), .. } +userOptionsWithAliases :: OptionMap+userOptionsWithAliases = foldl insert userOptions (leaves userOptions)+  where+  insert m d = foldl (\m' n -> insertTrie n d m') m (optAliases d)+ userOptions :: OptionMap userOptions  = mkOptionMap-  [ simpleOpt "base" (EnvNum 16) checkBase+  [ simpleOpt "base" [] (EnvNum 16) checkBase     "The base to display words at (2, 8, 10, or 16)."-  , simpleOpt "debug" (EnvBool False) noCheck+  , simpleOpt "debug" [] (EnvBool False) noCheck     "Enable debugging output."-  , simpleOpt "ascii" (EnvBool False) noCheck+  , simpleOpt "ascii" [] (EnvBool False) noCheck     "Whether to display 7- or 8-bit words using ASCII notation."-  , simpleOpt "infLength" (EnvNum 5) checkInfLength+  , simpleOpt "infLength" ["inf-length"] (EnvNum 5) checkInfLength     "The number of elements to display for infinite sequences."-  , simpleOpt "tests" (EnvNum 100) noCheck+  , simpleOpt "tests" [] (EnvNum 100) noCheck     "The number of random tests to try with ':check'."-  , simpleOpt "satNum" (EnvString "1") checkSatNum+  , simpleOpt "satNum" ["sat-num"] (EnvString "1") checkSatNum     "The maximum number of :sat solutions to display (\"all\" for no limit)."-  , simpleOpt "prover" (EnvString "z3") checkProver $+  , simpleOpt "prover" [] (EnvString "z3") checkProver $     "The external SMT solver for ':prove' and ':sat'\n(" ++ proverListString ++ ")."-  , simpleOpt "warnDefaulting" (EnvBool False) noCheck+  , simpleOpt "warnDefaulting" ["warn-defaulting"] (EnvBool False) noCheck     "Choose whether to display warnings when defaulting."-  , simpleOpt "warnShadowing" (EnvBool True) noCheck+  , simpleOpt "warnShadowing" ["warn-shadowing"] (EnvBool True) noCheck     "Choose whether to display warnings when shadowing symbols."-  , simpleOpt "warnUninterp" (EnvBool True) noCheck+  , simpleOpt "warnUninterp" ["warn-uninterp"] (EnvBool True) noCheck     "Choose whether to issue a warning when uninterpreted functions are used to implement primitives in the symbolic simulator."-  , simpleOpt "smtfile" (EnvString "-") noCheck+  , simpleOpt "smtFile" ["smt-file"] (EnvString "-") noCheck     "The file to use for SMT-Lib scripts (for debugging or offline proving).\nUse \"-\" for stdout."-  , OptionDescr "mono-binds" (EnvBool True) noCheck+  , OptionDescr "monoBinds" ["mono-binds"] (EnvBool True) noCheck     "Whether or not to generalize bindings in a 'where' clause." $     \case EnvBool b -> do me <- getModuleEnv                           setModuleEnv me { M.meMonoBinds = b }           _         -> return () -  , OptionDescr "tc-solver" (EnvProg "z3" [ "-smt2", "-in" ])+  , 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@@ -772,7 +822,7 @@                                                           , T.solverArgs = args } }           _                 -> return () -  , OptionDescr "tc-debug" (EnvNum 0)+  , OptionDescr "tcDebug" ["tc-debug"] (EnvNum 0)     noCheck     (unlines       [ "Enable type-checker debugging output:"@@ -783,7 +833,7 @@                          let cfg = M.meSolverConfig me                          setModuleEnv me { M.meSolverConfig = cfg{ T.solverVerbose = n } }           _        -> return ()-  , OptionDescr "core-lint" (EnvBool False)+  , OptionDescr "coreLint" ["core-lint"] (EnvBool False)     noCheck     "Enable sanity checking of type-checker." $       let setIt x = do me <- getModuleEnv@@ -792,22 +842,22 @@                EnvBool False -> setIt M.NoCoreLint                _             -> return () -  , simpleOpt "hash-consing" (EnvBool True) noCheck+  , simpleOpt "hashConsing" ["hash-consing"] (EnvBool True) noCheck     "Enable hash-consing in the What4 symbolic backends." -  , simpleOpt "prover-stats" (EnvBool True) noCheck+  , simpleOpt "proverStats" ["prover-stats"] (EnvBool True) noCheck     "Enable prover timing statistics." -  , simpleOpt "prover-validate" (EnvBool False) noCheck+  , simpleOpt "proverValidate" ["prover-validate"] (EnvBool False) noCheck     "Validate :sat examples and :prove counter-examples for correctness." -  , simpleOpt "show-examples" (EnvBool True) noCheck+  , simpleOpt "showExamples" ["show-examples"] (EnvBool True) noCheck     "Print the (counter) example after :sat or :prove" -  , simpleOpt "fp-base" (EnvNum 16) checkBase+  , simpleOpt "fpBase" ["fp-base"] (EnvNum 16) checkBase     "The base to display floating point numbers at (2, 8, 10, or 16)." -  , simpleOpt "fp-format" (EnvString "free") checkPPFloatFormat+  , simpleOpt "fpFormat" ["fp-format"] (EnvString "free") checkPPFloatFormat     $ unlines     [ "Specifies the format to use when showing floating point numbers:"     , "  * free      show using as many digits as needed"@@ -817,7 +867,7 @@     , "  * NUM+exp   like NUM but always show exponent"     ] -  , simpleOpt "ignore-safety" (EnvBool False) noCheck+  , simpleOpt "ignoreSafety" ["ignore-safety"] (EnvBool False) noCheck     "Ignore safety predicates when performing :sat or :prove checks"   ] 
src/Cryptol/REPL/Trie.hs view
@@ -9,6 +9,7 @@ module Cryptol.REPL.Trie where  import           Cryptol.Utils.Panic (panic)+import           Data.Char (toLower) import qualified Data.Map as Map import           Data.Maybe (fromMaybe,maybeToList) @@ -20,13 +21,13 @@ emptyTrie :: Trie a emptyTrie  = Node Map.empty Nothing --- | Insert a value into the Trie.  Will call `panic` if a value already exists--- with that key.+-- | Insert a value into the Trie, forcing the key value to lower case.+--   Will call `panic` if a value already exists with that key. insertTrie :: String -> a -> Trie a -> Trie a insertTrie k a = loop k   where   loop key (Node m mb) = case key of-    c:cs -> Node (Map.alter (Just . loop cs . fromMaybe emptyTrie) c m) mb+    c:cs -> Node (Map.alter (Just . loop cs . fromMaybe emptyTrie) (toLower c) m) mb     []   -> case mb of       Nothing -> Node m (Just a)       Just _  -> panic "[REPL] Trie" ["key already exists:", "\t" ++ k]@@ -35,7 +36,7 @@ lookupTrie :: String -> Trie a -> [a] lookupTrie key t@(Node mp _) = case key of -  c:cs -> case Map.lookup c mp of+  c:cs -> case Map.lookup (toLower c) mp of     Just m' -> lookupTrie cs m'     Nothing -> [] @@ -47,7 +48,7 @@ lookupTrieExact []     (Node _ (Just x)) = return x lookupTrieExact []     t                 = leaves t lookupTrieExact (c:cs) (Node mp _)       =-  case Map.lookup c mp of+  case Map.lookup (toLower c) mp of     Just m' -> lookupTrieExact cs m'     Nothing -> [] 
src/Cryptol/Symbolic.hs view
@@ -54,7 +54,8 @@ import qualified Cryptol.Eval.Concrete as Concrete import           Cryptol.Eval.Value import           Cryptol.TypeCheck.AST-import           Cryptol.Eval.Type (TValue(..), evalType)+import           Cryptol.TypeCheck.Solver.InfNat+import           Cryptol.Eval.Type (TValue(..), evalType,tValTy,tNumValTy) import           Cryptol.Utils.Ident (Ident,prelPrim,floatPrim) import           Cryptol.Utils.RecordMap import           Cryptol.Utils.Panic@@ -65,7 +66,7 @@ import Prelude.Compat import Data.Time (NominalDiffTime) -type SatResult = [(Type, Expr, Concrete.Value)]+type SatResult = [(TValue, Expr, Concrete.Value)]  data SatNum = AllSat | SomeSat Int   deriving (Show)@@ -108,7 +109,7 @@ -- for the offline prover), a counterexample or a lazy list of -- satisfying assignments. data ProverResult = AllSatResult [SatResult] -- LAZY-                  | ThmResult    [Type]+                  | ThmResult    [TValue]                   | CounterExample CounterExampleType SatResult                   | EmptyResult                   | ProverError  String@@ -141,41 +142,57 @@     | FTIntMod Integer     | FTRational     | FTFloat Integer Integer-    | FTSeq Int FinType+    | FTSeq Integer FinType     | FTTuple [FinType]     | FTRecord (RecordMap Ident FinType)--numType :: Integer -> Maybe Int-numType n-  | 0 <= n && n <= toInteger (maxBound :: Int) = Just (fromInteger n)-  | otherwise = Nothing+    | FTNewtype Newtype [Either Nat' TValue] (RecordMap Ident FinType)  finType :: TValue -> Maybe FinType finType ty =   case ty of-    TVBit            -> Just FTBit-    TVInteger        -> Just FTInteger-    TVIntMod n       -> Just (FTIntMod n)-    TVRational       -> Just FTRational-    TVFloat e p      -> Just (FTFloat e p)-    TVSeq n t        -> FTSeq <$> numType n <*> finType t-    TVTuple ts       -> FTTuple <$> traverse finType ts-    TVRec fields     -> FTRecord <$> traverse finType fields-    TVAbstract {}    -> Nothing-    _                     -> Nothing+    TVBit               -> Just FTBit+    TVInteger           -> Just FTInteger+    TVIntMod n          -> Just (FTIntMod n)+    TVRational          -> Just FTRational+    TVFloat e p         -> Just (FTFloat e p)+    TVSeq n t           -> FTSeq n <$> finType t+    TVTuple ts          -> FTTuple <$> traverse finType ts+    TVRec fields        -> FTRecord <$> traverse finType fields+    TVNewtype u ts body -> FTNewtype u ts <$> traverse finType body+    TVAbstract {}       -> Nothing+    TVArray{}           -> Nothing+    TVStream{}          -> Nothing+    TVFun{}             -> Nothing -unFinType :: FinType -> Type-unFinType fty =+finTypeToType :: FinType -> Type+finTypeToType fty =   case fty of-    FTBit        -> tBit-    FTInteger    -> tInteger-    FTIntMod n   -> tIntMod (tNum n)-    FTRational   -> tRational-    FTFloat e p  -> tFloat (tNum e) (tNum p)-    FTSeq l ety  -> tSeq (tNum l) (unFinType ety)-    FTTuple ftys -> tTuple (unFinType <$> ftys)-    FTRecord fs  -> tRec (unFinType <$> fs)+    FTBit             -> tBit+    FTInteger         -> tInteger+    FTIntMod n        -> tIntMod (tNum n)+    FTRational        -> tRational+    FTFloat e p       -> tFloat (tNum e) (tNum p)+    FTSeq l ety       -> tSeq (tNum l) (finTypeToType ety)+    FTTuple ftys      -> tTuple (finTypeToType <$> ftys)+    FTRecord fs       -> tRec (finTypeToType <$> fs)+    FTNewtype u ts _  -> tNewtype u (map unArg ts)+ where+  unArg (Left Inf)     = tInf+  unArg (Left (Nat n)) = tNum n+  unArg (Right t)      = tValTy t +unFinType :: FinType -> TValue+unFinType fty =+  case fty of+    FTBit             -> TVBit+    FTInteger         -> TVInteger+    FTIntMod n        -> TVIntMod n+    FTRational        -> TVRational+    FTFloat e p       -> TVFloat e p+    FTSeq n ety       -> TVSeq n (unFinType ety)+    FTTuple ftys      -> TVTuple (unFinType <$> ftys)+    FTRecord fs       -> TVRec   (unFinType <$> fs)+    FTNewtype u ts fs -> TVNewtype u ts (unFinType <$> fs)  data VarShape sym   = VarBit (SBit sym)@@ -188,12 +205,11 @@   | VarRecord (RecordMap Ident (VarShape sym))  ppVarShape :: Backend sym => sym -> VarShape sym -> Doc-ppVarShape sym (VarBit b) = ppBit sym b-ppVarShape sym (VarInteger i) = ppInteger sym defaultPPOpts i-ppVarShape sym (VarFloat f) = ppFloat sym defaultPPOpts f-ppVarShape sym (VarRational n d) =-  text "(ratio" <+> ppInteger sym defaultPPOpts n <+> ppInteger sym defaultPPOpts d <+> text ")"-ppVarShape sym (VarWord w) = ppWord sym defaultPPOpts w+ppVarShape _sym (VarBit _b) = text "<bit>"+ppVarShape _sym (VarInteger _i) = text "<integer>"+ppVarShape _sym (VarFloat _f) = text "<float>"+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))) ppVarShape sym (VarTuple xs) =@@ -212,7 +228,7 @@     VarRational n d -> VRational (SRational n d)     VarWord w    -> VWord (wordLen sym w) (return (WordVal w))     VarFloat f   -> VFloat f-    VarFinSeq n vs -> VSeq n (finiteSeqMap sym (map (pure . varShapeToValue sym) vs))+    VarFinSeq n vs -> VSeq n (finiteSeqMap (map (pure . varShapeToValue sym) vs))     VarTuple vs  -> VTuple (map (pure . varShapeToValue sym) vs)     VarRecord fs -> VRecord (fmap (pure . varShapeToValue sym) fs) @@ -225,7 +241,8 @@   }  freshVar :: Backend sym => FreshVarFns sym -> FinType -> IO (VarShape sym)-freshVar fns tp = case tp of+freshVar fns tp =+  case tp of     FTBit         -> VarBit      <$> freshBitVar fns     FTInteger     -> VarInteger  <$> freshIntegerVar fns Nothing Nothing     FTRational    -> VarRational@@ -234,16 +251,17 @@     FTIntMod 0    -> panic "freshVariable" ["0 modulus not allowed"]     FTIntMod m    -> VarInteger  <$> freshIntegerVar fns (Just 0) (Just (m-1))     FTFloat e p   -> VarFloat    <$> freshFloatVar fns e p-    FTSeq n FTBit | n > 0 -> VarWord     <$> freshWordVar fns (toInteger n)+    FTSeq n FTBit -> VarWord     <$> freshWordVar fns (toInteger n)     FTSeq n t     -> VarFinSeq (toInteger n) <$> sequence (genericReplicate n (freshVar fns t))     FTTuple ts    -> VarTuple    <$> mapM (freshVar fns) ts     FTRecord fs   -> VarRecord   <$> traverse (freshVar fns) fs+    FTNewtype _ _ fs -> VarRecord <$> traverse (freshVar fns) fs  computeModel ::   PrimMap ->   [FinType] ->   [VarShape Concrete.Concrete] ->-  [(Type, Expr, Concrete.Value)]+  [(TValue, Expr, Concrete.Value)] computeModel _ [] [] = [] computeModel primMap (t:ts) (v:vs) =   do let v' = varShapeToValue Concrete.Concrete v@@ -304,6 +322,14 @@   go :: FinType -> VarShape Concrete.Concrete -> Expr   go ty val =     case (ty,val) of+      (FTNewtype nt ts tfs, VarRecord vfs) ->+        let res = zipRecords (\_lbl v t -> go t v) vfs tfs+         in case res of+              Left _ -> mismatch -- different fields+              Right efs ->+                let f = foldl (\x t -> ETApp x (tNumValTy t)) (EVar (ntName nt)) ts+                 in EApp f (ERec efs)+       (FTRecord tfs, VarRecord vfs) ->         let res = zipRecords (\_lbl v t -> go t v) vfs tfs          in case res of@@ -317,11 +343,11 @@        (FTInteger, VarInteger i) ->         -- This works uniformly for values of type Integer or Z n-        ETApp (ETApp (prim "number") (tNum i)) (unFinType ty)+        ETApp (ETApp (prim "number") (tNum i)) (finTypeToType ty)        (FTIntMod _, VarInteger i) ->         -- This works uniformly for values of type Integer or Z n-        ETApp (ETApp (prim "number") (tNum i)) (unFinType ty)+        ETApp (ETApp (prim "number") (tNum i)) (finTypeToType ty)        (FTRational, VarRational n d) ->         let n' = ETApp (ETApp (prim "number") (tNum n)) tInteger@@ -332,17 +358,17 @@         floatToExpr prims e p (bfValue f)        (FTSeq _ FTBit, VarWord (Concrete.BV _ v)) ->-        ETApp (ETApp (prim "number") (tNum v)) (unFinType ty)+        ETApp (ETApp (prim "number") (tNum v)) (finTypeToType ty)        (FTSeq _ t, VarFinSeq _ svs) ->-        EList (map (go t) svs) (unFinType t)+        EList (map (go t) svs) (finTypeToType t)        _ -> mismatch     where       mismatch =            panic "Cryptol.Symbolic.varToExpr"              ["type mismatch:"-             , show (pp (unFinType ty))+             , show (pp (finTypeToType ty))              , show (ppVarShape Concrete.Concrete val)              ] 
src/Cryptol/Symbolic/SBV.hs view
@@ -6,6 +6,7 @@ -- Stability   :  provisional -- Portability :  portable +{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ImplicitParams #-} {-# LANGUAGE LambdaCase #-}@@ -57,6 +58,7 @@ import qualified Cryptol.Eval.Concrete as Concrete import qualified Cryptol.Eval.Value as Eval import           Cryptol.Eval.SBV+import           Cryptol.Parser.Position (emptyRange) import           Cryptol.Symbolic import           Cryptol.TypeCheck.AST import           Cryptol.Utils.Ident (preludeReferenceName, prelPrim, identText)@@ -70,7 +72,7 @@  doSBVEval :: MonadIO m => SBVEval a -> m (SBV.SVal, a) doSBVEval m =-  (liftIO $ Eval.runEval (sbvEval m)) >>= \case+  (liftIO $ Eval.runEval mempty (sbvEval m)) >>= \case     SBVError err -> liftIO (X.throwIO err)     SBVResult p x -> pure (p, x) @@ -124,7 +126,11 @@ setupProver :: String -> IO (Either String ([String], SBVProverConfig)) setupProver nm   | nm `elem` ["any","sbv-any"] =+#if MIN_VERSION_sbv(8,9,0)+    do ps <- SBV.getAvailableSolvers+#else     do ps <- SBV.sbvAvailableSolvers+#endif        case ps of          [] -> pure (Left "SBV could not find any provers")          _ ->  let msg = "SBV found the following solvers: " ++ show (map (SBV.name . SBV.solver) ps) in@@ -155,14 +161,18 @@ satSMTResults (SBV.SatResult r) = [r]  allSatSMTResults :: SBV.AllSatResult -> [SBV.SMTResult]+#if MIN_VERSION_sbv(8,8,0)+allSatSMTResults (SBV.AllSatResult {allSatResults = rs}) = rs+#else allSatSMTResults (SBV.AllSatResult (_, _, _, rs)) = rs+#endif  thmSMTResults :: SBV.ThmResult -> [SBV.SMTResult] thmSMTResults (SBV.ThmResult r) = [r]  proverError :: String -> M.ModuleCmd (Maybe String, ProverResult)-proverError msg (_, _, modEnv) =-  return (Right ((Nothing, ProverError msg), modEnv), [])+proverError msg minp =+  return (Right ((Nothing, ProverError msg), M.minpModuleEnv minp), [])   isFailedResult :: [SBV.SMTResult] -> Maybe String@@ -297,6 +307,13 @@      modEnv <- M.getModuleEnv      let extDgs = M.allDeclGroups modEnv ++ pcExtraDecls +     callStacks <- M.getCallStacks+     let ?callStacks = callStacks++     getEOpts <- M.getEvalOptsAction++     ntEnv <- M.getNewtypes+      -- The `addAsm` function is used to combine assumptions that      -- arise from the types of symbolic variables (e.g. Z n values      -- are assumed to be integers in the range `0 <= x < n`) with@@ -316,9 +333,11 @@                  stateMVar <- liftIO (newMVar sbvState)                  defRelsVar <- liftIO (newMVar SBV.svTrue)                  let sym = SBV stateMVar defRelsVar-                 let tbl = primTable sym+                 let tbl = primTable sym getEOpts                  let ?evalPrim = \i -> (Right <$> Map.lookup i tbl) <|>                                        (Left <$> Map.lookup i ds)+                 let ?range = emptyRange+                  -- Compute the symbolic inputs, and any domain constraints needed                  -- according to their types.                  args <- map (pure . varShapeToValue sym) <$>@@ -327,9 +346,10 @@                  -- evaluation environment, then we compute the value, finally                  -- we apply it to the symbolic inputs.                  (safety,b) <- doSBVEval $-                     do env <- Eval.evalDecls sym extDgs mempty+                     do env <- Eval.evalDecls sym extDgs =<<+                                 Eval.evalNewtypeDecls sym ntEnv mempty                         v <- Eval.evalExpr sym env pcExpr-                        appliedVal <- foldM Eval.fromVFun v args+                        appliedVal <- foldM (Eval.fromVFun sym) v args                         case pcQueryType of                           SafetyQuery ->                             do Eval.forceValue appliedVal@@ -389,7 +409,11 @@         -- otherwise something is wrong        _ -> return $ ProverError (rshow results)+#if MIN_VERSION_sbv(8,8,0)+              where rshow | isSat = show . (SBV.AllSatResult False False False False)+#else               where rshow | isSat = show .  SBV.AllSatResult . (False,False,False,)+#endif                           | otherwise = show . SBV.ThmResult . head    where@@ -398,7 +422,7 @@     -- to always be the first value in the model assignment list.     let Right (_, (safetyCV : cvs)) = SBV.getModelAssignment result         safety = SBV.cvToBool safetyCV-        (vs, []) = parseValues ts cvs+        (vs, _) = parseValues ts cvs         mdl = computeModel prims ts vs     return (safety, mdl) @@ -409,10 +433,10 @@ --   solver that completes the given query (if any) along with the result --   of executing the query. satProve :: SBVProverConfig -> ProverCommand -> M.ModuleCmd (Maybe String, ProverResult)-satProve proverCfg pc@ProverCommand {..} =-  protectStack proverError $ \(evo, byteReader, modEnv) ->--  M.runModuleM (evo, byteReader, modEnv) $ do+satProve proverCfg pc =+  protectStack proverError $ \minp ->+  M.runModuleM minp $ do+  evo <- liftIO (M.minpEvalOpts minp)    let lPutStrLn = logPutStrLn (Eval.evalLogger evo) @@ -431,12 +455,13 @@ --   the SMT input file corresponding to the given prover command. satProveOffline :: SBVProverConfig -> ProverCommand -> M.ModuleCmd (Either String String) satProveOffline _proverCfg pc@ProverCommand {..} =-  protectStack (\msg (_,_,modEnv) -> return (Right (Left msg, modEnv), [])) $-  \(evo, byteReader, modEnv) -> M.runModuleM (evo,byteReader,modEnv) $+  protectStack (\msg minp -> return (Right (Left msg, M.minpModuleEnv minp), [])) $+  \minp -> M.runModuleM minp $      do let isSat = case pcQueryType of               ProveQuery -> False               SafetyQuery -> False               SatQuery _ -> True+        evo <- liftIO (M.minpEvalOpts minp)          prepareQuery evo pc >>= \case           Left msg -> return (Left msg)@@ -479,11 +504,11 @@      return (VarRational n d, cvs'') parseValue (FTSeq 0 FTBit) cvs = (VarWord (Concrete.mkBv 0 0), cvs) parseValue (FTSeq n FTBit) cvs =-  case SBV.genParse (SBV.KBounded False n) cvs of+  case SBV.genParse (SBV.KBounded False (fromInteger n)) cvs of     Just (x, cvs') -> (VarWord (Concrete.mkBv (toInteger n) x), cvs')     Nothing -> panic "Cryptol.Symbolic.parseValue" ["no bitvector"] parseValue (FTSeq n t) cvs = (VarFinSeq (toInteger n) vs, cvs')-  where (vs, cvs') = parseValues (replicate n t) cvs+  where (vs, cvs') = parseValues (replicate (fromInteger n) t) cvs parseValue (FTTuple ts) cvs = (VarTuple vs, cvs')   where (vs, cvs') = parseValues ts cvs parseValue (FTRecord r) cvs = (VarRecord r', cvs')@@ -492,6 +517,8 @@         fs         = zip ns vs         r'         = recordFromFieldsWithDisplay (displayOrder r) fs +parseValue (FTNewtype _ _ r) cvs = parseValue (FTRecord r) cvs+ parseValue (FTFloat e p) cvs =    (VarFloat FH.BF { FH.bfValue = bfNaN                    , FH.bfExpWidth = e@@ -513,11 +540,16 @@        Nothing -> pure ()      return x +freshBitvector :: SBV -> Integer -> IO SBV.SVal+freshBitvector sym w+  | w == 0 = pure (SBV.svInteger (SBV.KBounded False 0) 0)+  | otherwise = freshBV_ sym (fromInteger w)+ sbvFreshFns :: SBV -> FreshVarFns SBV sbvFreshFns sym =   FreshVarFns   { freshBitVar     = freshSBool_ sym-  , freshWordVar    = freshBV_ sym . fromInteger+  , freshWordVar    = freshBitvector sym   , freshIntegerVar = freshBoundedInt sym   , freshFloatVar   = \_ _ -> return () -- TODO   }
src/Cryptol/Symbolic/What4.hs view
@@ -56,12 +56,12 @@  import qualified Cryptol.Backend.FloatHelpers as FH import           Cryptol.Backend.What4-import qualified Cryptol.Backend.What4.SFloat as W4  import qualified Cryptol.Eval as Eval import qualified Cryptol.Eval.Concrete as Concrete import qualified Cryptol.Eval.Value as Eval import           Cryptol.Eval.What4+import           Cryptol.Parser.Position (emptyRange) import           Cryptol.Symbolic import           Cryptol.TypeCheck.AST import           Cryptol.Utils.Logger(logPutStrLn,logPutStr,Logger)@@ -72,6 +72,7 @@ import qualified What4.Expr.Builder as W4 import qualified What4.Expr.GroundEval as W4 import qualified What4.SatResult as W4+import qualified What4.SFloat as W4 import qualified What4.SWord as SW import           What4.Solver import qualified What4.Solver.Adapter as W4@@ -123,7 +124,7 @@   (W4.IsExprBuilder sym, MonadIO m) =>   sym -> W4Eval sym a -> m (W4.Pred sym, a) doW4Eval sym m =-  do res <- liftIO $ Eval.runEval (w4Eval m sym)+  do res <- liftIO $ Eval.runEval mempty (w4Eval m sym)      case res of        W4Error err  -> liftIO (X.throwIO err)        W4Result p x -> pure (p,x)@@ -198,8 +199,8 @@   proverError :: String -> M.ModuleCmd (Maybe String, ProverResult)-proverError msg (_, _, modEnv) =-  return (Right ((Nothing, ProverError msg), modEnv), [])+proverError msg minp =+  return (Right ((Nothing, ProverError msg), M.minpModuleEnv minp), [])   data CryptolState t = CryptolState@@ -234,12 +235,13 @@   M.ModuleT IO (Either String                        ([FinType],[VarShape (What4 sym)],W4.Pred sym, W4.Pred sym)                )-prepareQuery sym ProverCommand { .. } =+prepareQuery sym ProverCommand { .. } = do+  ntEnv <- M.getNewtypes   case predArgTypes pcQueryType pcSchema of     Left msg -> pure (Left msg)     Right ts ->       do args <- liftIO (mapM (freshVar (what4FreshFns (w4 sym))) ts)-         (safety,b) <- simulate args+         (safety,b) <- simulate ntEnv args          liftIO            do -- Ignore the safety condition if the flag is set               let safety' = if pcIgnoreSafety then W4.truePred (w4 sym) else safety@@ -263,7 +265,7 @@                        q' <- W4.andPred (w4 sym) defs q                        pure (ts,args,safety',q')   where-  simulate args =+  simulate ntEnv args =     do let lPutStrLn = M.withLogger logPutStrLn        when pcVerbose (lPutStrLn "Simulating...") @@ -273,18 +275,24 @@                 let ds = Map.fromList [ (prelPrim (identText (M.nameIdent nm)), EWhere (EVar nm) decls) | nm <- nms ]                 pure ds -       let tbl = primTable sym+       getEOpts <- M.getEvalOptsAction+       let tbl = primTable sym getEOpts        let ?evalPrim = \i -> (Right <$> Map.lookup i tbl) <|>                              (Left <$> Map.lookup i ds)+       let ?range = emptyRange+       callStacks <- M.getCallStacks+       let ?callStacks = callStacks         modEnv <- M.getModuleEnv        let extDgs = M.allDeclGroups modEnv ++ pcExtraDecls         doW4Eval (w4 sym)-         do env <- Eval.evalDecls sym extDgs mempty+         do env <- Eval.evalDecls sym extDgs =<<+                     Eval.evalNewtypeDecls sym ntEnv mempty+             v   <- Eval.evalExpr  sym env    pcExpr             appliedVal <--              foldM Eval.fromVFun v (map (pure . varShapeToValue sym) args)+              foldM (Eval.fromVFun sym) v (map (pure . varShapeToValue sym) args)              case pcQueryType of               SafetyQuery ->@@ -302,8 +310,8 @@   M.ModuleCmd (Maybe String, ProverResult)  satProve solverCfg hashConsing warnUninterp ProverCommand {..} =-  protectStack proverError \(evo, byteReader, modEnv) ->-  M.runModuleM (evo, byteReader, modEnv)+  protectStack proverError \modIn ->+  M.runModuleM modIn   do w4sym   <- liftIO makeSym      defVar  <- liftIO (newMVar (W4.truePred w4sym))      funVar  <- liftIO (newMVar mempty)@@ -374,8 +382,8 @@   satProveOffline (W4ProverConfig p) hashConsing warnUninterp cmd outputContinuation  satProveOffline (W4ProverConfig (AnAdapter adpt)) hashConsing warnUninterp ProverCommand {..} outputContinuation =-  protectStack onError \(evo,byteReader,modEnv) ->-  M.runModuleM (evo,byteReader,modEnv)+  protectStack onError \modIn ->+  M.runModuleM modIn    do w4sym <- liftIO makeSym       defVar  <- liftIO (newMVar (W4.truePred w4sym))       funVar  <- liftIO (newMVar mempty)@@ -400,7 +408,7 @@        when hashConsing  (W4.startCaching sym)        pure sym -  onError msg (_,_,modEnv) = pure (Right (Just msg, modEnv), [])+  onError msg minp = pure (Right (Just msg, M.minpModuleEnv minp), [])   decSatNum :: SatNum -> SatNum@@ -545,8 +553,8 @@       let w = W4.intValue (W4.bvWidth x)        in VarWord . Concrete.mkBv w . BV.asUnsigned <$> W4.groundEval evalFn x     VarFloat fv@(W4.SFloat f) ->-      do let (e,p) = W4.fpSize fv-         VarFloat . FH.floatFromBits e p . BV.asUnsigned <$> W4.groundEval evalFn f+      let (e,p) = W4.fpSize fv+       in VarFloat . FH.BF e p <$> W4.groundEval evalFn f     VarFinSeq n vs ->       VarFinSeq n <$> mapM (varShapeToConcrete evalFn) vs     VarTuple vs ->
src/Cryptol/Testing/Random.hs view
@@ -10,6 +10,7 @@  {-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE Trustworthy #-}@@ -19,7 +20,6 @@ , randomValue , dumpableType , testableType-, TestReport(..) , TestResult(..) , isPass , returnTests@@ -28,21 +28,23 @@ ) where  import qualified Control.Exception as X-import Control.Monad          (join, liftM2)+import Control.Monad          (liftM2) import Control.Monad.IO.Class (MonadIO(..))-import Data.Ratio             ((%))+import Data.Bits import Data.List              (unfoldr, genericTake, genericIndex, genericReplicate) import qualified Data.Sequence as Seq  import System.Random          (RandomGen, split, random, randomR)  import Cryptol.Backend        (Backend(..), SRational(..))-import Cryptol.Backend.Monad  (runEval,Eval,EvalError(..))+import Cryptol.Backend.FloatHelpers (floatFromBits)+import Cryptol.Backend.Monad  (runEval,Eval,EvalErrorEx(..)) import Cryptol.Backend.Concrete  import Cryptol.Eval.Type      (TValue(..)) import Cryptol.Eval.Value     (GenValue(..),SeqMap(..), WordValue(..),-                               ppValue, defaultPPOpts, finiteSeqMap)+                               ppValue, defaultPPOpts, finiteSeqMap, fromVFun)+import Cryptol.TypeCheck.Solver.InfNat (widthInteger) import Cryptol.Utils.Ident    (Ident) import Cryptol.Utils.Panic    (panic) import Cryptol.Utils.RecordMap@@ -68,7 +70,7 @@ runOneTest fun argGens sz g0 = do   let (args, g1) = foldr mkArg ([], g0) argGens       mkArg argGen (as, g) = let (a, g') = argGen sz g in (a:as, g')-  args' <- runEval (sequence args)+  args' <- runEval mempty (sequence args)   result <- evalTest fun args'   return (result, g1) @@ -81,12 +83,14 @@ returnOneTest fun argGens sz g0 =   do let (args, g1) = foldr mkArg ([], g0) argGens          mkArg argGen (as, g) = let (a, g') = argGen sz g in (a:as, g')-     args' <- runEval (sequence args)-     result <- runEval (go fun args')+     args' <- runEval mempty (sequence args)+     result <- runEval mempty (go fun args')      return (args', result, g1)    where-     go (VFun f) (v : vs) = join (go <$> (f (pure v)) <*> pure vs)-     go (VFun _) [] = panic "Cryptol.Testing.Random" ["Not enough arguments to function while generating tests"]+     go f@VFun{} (v : vs) =+       do f' <- fromVFun Concrete f (pure v)+          go f' vs+     go VFun{} [] = panic "Cryptol.Testing.Random" ["Not enough arguments to function while generating tests"]      go _ (_ : _) = panic "Cryptol.Testing.Random" ["Too many arguments to function while generating tests"]      go v [] = return v @@ -147,7 +151,9 @@     TVRec fs ->          do gs <- traverse (randomValue sym) fs             return (randomRecord gs)-+    TVNewtype _ _ fs ->+         do gs <- traverse (randomValue sym) fs+            return (randomRecord gs)     TVArray{} -> Nothing     TVFun{} -> Nothing     TVAbstract{} -> Nothing@@ -226,7 +232,8 @@   let f g = let (x,g') = mkElem sz g              in seq x (Just (x, g'))   let xs = Seq.fromList $ genericTake w $ unfoldr f g1-  seq xs (pure $ VSeq w $ IndexSeqMap $ (Seq.index xs . fromInteger), g2)+  let v  = VSeq w $ IndexSeqMap $ \i -> Seq.index xs (fromInteger i)+  seq xs (pure v, g2)  {-# INLINE randomTuple #-} @@ -256,20 +263,42 @@   Integer {- ^ Exponent width -} ->   Integer {- ^ Precision width -} ->   Gen g sym-randomFloat sym e p w g =-  ( VFloat <$> fpLit sym e p (nu % de)-  , g3-  )+randomFloat sym e p w g0 =+    let sz = max 0 (min 100 w)+        ( x, g') = randomR (0, 10*(sz+1)) g0+     in if | x < 2    -> (VFloat <$> fpNaN sym e p, g')+           | x < 4    -> (VFloat <$> fpPosInf sym e p, g')+           | x < 6    -> (VFloat <$> (fpNeg sym =<< fpPosInf sym e p), g')+           | x < 8    -> (VFloat <$> fpLit sym e p 0, g')+           | x < 10   -> (VFloat <$> (fpNeg sym =<< fpLit sym e p 0), g')+           | x <= sz       -> genSubnormal g'  -- about 10% of the time+           | x <= 4*(sz+1) -> genBinary g'     -- about 40%+           | otherwise     -> genNormal (toInteger sz) g'  -- remaining ~50%+   where-  -- XXX: we never generat NaN-  -- XXX: Not sure that we need such big integers, we should probably-  -- use `e` and `p` as a guide.-  (n,  g1) = if w < 100 then (fromInteger w, g) else randomSize 8 100 g-  (nu, g2) = randomR (- 256^n, 256^n) g1-  (de, g3) = randomR (1, 256^n) g2+    emax = bit (fromInteger e) - 1+    smax = bit (fromInteger p) - 1 +    -- generates floats uniformly chosen from among all bitpatterns+    genBinary g =+      let (v, g1) = randomR (0, bit (fromInteger (e+p)) - 1) g+       in (VFloat <$> (fpFromBits sym e p =<< wordLit sym (e+p) v), g1) +    -- generates floats corresponding to subnormal values.  These are+    -- values with 0 biased exponent and nonzero mantissa.+    genSubnormal g =+      let (sgn, g1) = random g+          (v, g2)   = randomR (1, bit (fromInteger p) - 1) g1+       in (VFloat <$> ((if sgn then fpNeg sym else pure) =<< fpFromBits sym e p =<< wordLit sym (e+p) v), g2) +    -- generates floats where the exponent and mantissa are scaled by the size+    genNormal sz g =+      let (sgn, g1) = random g+          (ex,  g2) = randomR ((1-emax)*sz `div` 100, (sz*emax) `div` 100) g1+          (mag, g3) = randomR (1, max 1 ((sz*smax) `div` 100)) g2+          r  = fromInteger mag ^^ (ex - widthInteger mag)+          r' = if sgn then negate r else r+       in (VFloat <$> fpLit sym e p r', g3)   -- | A test result is either a pass, a failure due to evaluating to@@ -277,7 +306,7 @@ data TestResult   = Pass   | FailFalse [Value]-  | FailError EvalError [Value]+  | FailError EvalErrorEx [Value]  isPass :: TestResult -> Bool isPass Pass = True@@ -291,15 +320,16 @@ evalTest v0 vs0 = run `X.catch` handle   where     run = do-      result <- runEval (go v0 vs0)+      result <- runEval mempty (go v0 vs0)       if result         then return Pass         else return (FailFalse vs0)     handle e = return (FailError e vs0)      go :: Value -> [Value] -> Eval Bool-    go (VFun f) (v : vs) = join (go <$> (f (pure v)) <*> return vs)-    go (VFun _) []       = panic "Not enough arguments while applying function"+    go f@VFun{} (v : vs) = do f' <- fromVFun Concrete f (pure v)+                              go f' vs+    go VFun{}   []       = panic "Not enough arguments while applying function"                            []     go (VBit b) []       = return b     go v vs              = do vdoc    <- ppValue Concrete defaultPPOpts v@@ -348,7 +378,7 @@   TVInteger -> Nothing   TVRational -> Nothing   TVIntMod n -> Just n-  TVFloat{} -> Nothing -- TODO?+  TVFloat e p -> Just (2 ^ (e+p))   TVArray{} -> Nothing   TVStream{} -> Nothing   TVSeq n el -> (^ n) <$> typeSize el@@ -356,25 +386,26 @@   TVRec fs -> product <$> traverse typeSize fs   TVFun{} -> Nothing   TVAbstract{} -> Nothing+  TVNewtype _ _ tbody -> typeSize (TVRec tbody)  {- | Returns all the values in a type.  Returns an empty list of values, for types where 'typeSize' returned 'Nothing'. -} typeValues :: TValue -> [Value] typeValues ty =   case ty of-    TVBit      -> [ VBit False, VBit True ]-    TVInteger  -> []-    TVRational -> []-    TVIntMod n -> [ VInteger x | x <- [ 0 .. (n-1) ] ]-    TVFloat{}  -> [] -- TODO?-    TVArray{}  -> []-    TVStream{} -> []+    TVBit       -> [ VBit False, VBit True ]+    TVInteger   -> []+    TVRational  -> []+    TVIntMod n  -> [ VInteger x | x <- [ 0 .. (n-1) ] ]+    TVFloat e p -> [ VFloat (floatFromBits e p v) | v <- [0 .. 2^(e+p) - 1] ]+    TVArray{}   -> []+    TVStream{}  -> []     TVSeq n TVBit ->       [ VWord n (pure (WordVal (BV n x)))       | x <- [ 0 .. 2^n - 1 ]       ]     TVSeq n el ->-      [ VSeq n (finiteSeqMap Concrete (map pure xs))+      [ VSeq n (finiteSeqMap (map pure xs))       | xs <- sequence (genericReplicate n (typeValues el))       ]     TVTuple ts ->@@ -387,16 +418,10 @@       ]     TVFun{} -> []     TVAbstract{} -> []+    TVNewtype _ _ tbody -> typeValues (TVRec tbody)  -------------------------------------------------------------------------------- -- Driver function--data TestReport = TestReport {-    reportResult :: TestResult-  , reportProp :: String -- ^ The property as entered by the user-  , reportTestsRun :: Integer-  , reportTestsPossible :: Maybe Integer-  }  exhaustiveTests :: MonadIO m =>   (Integer -> m ()) {- ^ progress callback -} ->
src/Cryptol/Transform/AddModParams.hs view
@@ -230,6 +230,7 @@         in ESel (EVar paramModRecParam) (RecordSel (nameIdent x) (Just sh))       | otherwise -> EVar x +     ELocated r t -> ELocated r (inst ps t)      EList es t -> EList (inst ps es) (inst ps t)      ETuple es -> ETuple (inst ps es)      ERec fs   -> ERec (fmap (inst ps) fs)@@ -288,17 +289,13 @@         where ts1 = inst ps ts               t1  = inst ps t -      TCon tc ts ->-        case tc of-          TC (TCNewtype (UserTC x k))-            | needsInst ps x -> TCon (TC (TCNewtype (UserTC x (k1 k))))-                                     (newTs ++ ts1)-          _ -> TCon tc ts1-        where-        ts1 = inst ps ts-        newTs = instTyParams ps-        k1 k = foldr (:->) k (map kindOf newTs)+      TNewtype nt ts+        | needsInst ps (ntName nt) -> TNewtype (inst ps nt) (instTyParams ps ++ ts1)+        | otherwise -> TNewtype nt ts1+        where ts1 = inst ps ts +      TCon tc ts -> TCon tc (inst ps ts)+       TVar x | Just x' <- isTParam ps x -> TVar (TVBound x')              | otherwise  -> ty @@ -311,7 +308,7 @@  instance Inst Newtype where   inst ps nt = nt { ntConstraints = inst ps (ntConstraints nt)-                  , ntFields = [ (f, inst ps t) | (f,t) <- ntFields nt ]+                  , ntFields = fmap (inst ps) (ntFields nt)                   }  
src/Cryptol/Transform/MonoValues.hs view
@@ -179,6 +179,7 @@                           Nothing  -> EProofApp <$> go e                           Just yes -> return yes +      ELocated r t    -> ELocated r <$> go t       EList es t      -> EList   <$> mapM go es <*> return t       ETuple es       -> ETuple  <$> mapM go es       ERec fs         -> ERec    <$> traverse go fs
src/Cryptol/Transform/Specialize.hs view
@@ -59,17 +59,18 @@ -- type-specialized versions of all functions called (transitively) by -- the body of the expression. specialize :: Expr -> M.ModuleCmd Expr-specialize expr (ev, byteReader, modEnv) = run $ do-  let extDgs = allDeclGroups modEnv+specialize expr minp = run $ do+  let extDgs = allDeclGroups (M.minpModuleEnv minp)   let (tparams, expr') = destETAbs expr   spec' <- specializeEWhere expr' extDgs   return (foldr ETAbs spec' tparams)   where-  run = M.runModuleT (ev, byteReader, modEnv) . fmap fst . runSpecT Map.empty+  run = M.runModuleT minp . fmap fst . runSpecT Map.empty  specializeExpr :: Expr -> SpecM Expr specializeExpr expr =   case expr of+    ELocated r e  -> ELocated r <$> specializeExpr e     EList es t    -> EList <$> traverse specializeExpr es <*> pure t     ETuple es     -> ETuple <$> traverse specializeExpr es     ERec fs       -> ERec <$> traverse specializeExpr fs
src/Cryptol/TypeCheck.hs view
@@ -52,6 +52,8 @@ import           Cryptol.Utils.PP import           Cryptol.Utils.Panic(panic) ++ tcModule :: P.Module Name -> InferInput -> IO (InferOutput Module) tcModule m inp = runInferM inp (inferModule m) @@ -78,7 +80,9 @@   where   go loc expr =     case expr of-      P.ELocated e loc' -> go loc' e+      P.ELocated e loc' ->+        do (te, sch) <- go loc' e+           pure $! if inpCallStacks inp then (ELocated loc' te, sch) else (te,sch)       P.EVar x  ->         do res <- lookupVar x            case res of
src/Cryptol/TypeCheck/AST.hs view
@@ -28,7 +28,7 @@   , module Cryptol.TypeCheck.Type   ) where -import Cryptol.Parser.Position(Located)+import Cryptol.Parser.Position(Located,Range,HasLoc(..)) import Cryptol.ModuleSystem.Name import Cryptol.ModuleSystem.Exports(ExportSpec(..)                                    , isExportedBind, isExportedType)@@ -124,6 +124,8 @@             | EAbs Name Type Expr       -- ^ Function value  +            | ELocated Range Expr       -- ^ Source location information+             {- | Proof abstraction.  Because we don't keep proofs around                  we don't need to name the assumption, but we still need to                  record the assumption.  The assumption is the 'Type' term,@@ -200,6 +202,8 @@ instance PP (WithNames Expr) where   ppPrec prec (WithNames expr nm) =     case expr of+      ELocated _ t  -> ppWP prec t+       EList [] t    -> optParens (prec > 0)                     $ text "[]" <+> colon <+> ppWP prec t @@ -319,7 +323,9 @@   (ts,e2) = splitWhile splitTApp e1  -+instance HasLoc Expr where+  getLoc (ELocated r _) = Just r+  getLoc _ = Nothing  instance PP Expr where   ppPrec n t = ppWithNamesPrec IntMap.empty n t
src/Cryptol/TypeCheck/CheckModuleInstance.hs view
@@ -112,7 +112,7 @@            src = CtPartialTypeFun nm        mapM_ (newGoal src) (ntConstraints nt) -       return (tp, TCon (TC (TCNewtype (UserTC nm k2))) [])+       return (tp, TNewtype nt [])    -- Check that a type parameter defined as another type parameter is OK   checkTP tp tp1 =
src/Cryptol/TypeCheck/Default.hs view
@@ -3,7 +3,7 @@ import qualified Data.Set as Set import           Data.Map (Map) import qualified Data.Map as Map-import Data.Maybe(mapMaybe)+import Data.Maybe(mapMaybe, isJust) import Data.List((\\),nub) import Control.Monad(guard,mzero) @@ -35,14 +35,16 @@   allProps = saturatedPropSet gSet   has p a  = Set.member (p (TVar a)) allProps +  isLiteralGoal a = isJust (Map.lookup a (literalGoals gSet)) ||+                    isJust (Map.lookup a (literalLessThanGoals gSet))   tryDefVar a =     -- If there is an `FLiteral` constraint we use that for defaulting.     case Map.lookup a (flitDefaultCandidates gSet) of       Just m -> m        -- Otherwise we try to use a `Literal`-      Nothing ->-        do _gt <- Map.lookup a (literalGoals gSet)+      Nothing+        | isLiteralGoal a -> do            defT <- if has pLogic a then mzero                    else if has pField a && not (has pIntegral a)                           then pure tRational@@ -56,6 +58,7 @@            -- to depend on            return ((a,defT),w) +        | otherwise -> mzero  flitDefaultCandidates :: Goals -> Map TVar (Maybe ((TVar,Type),Warning)) flitDefaultCandidates gs =
src/Cryptol/TypeCheck/Depends.hs view
@@ -15,9 +15,10 @@ import           Cryptol.Parser.Position(Range, Located(..), thing) import           Cryptol.Parser.Names (namesB, tnamesT, tnamesC,                                       boundNamesSet, boundNames)-import           Cryptol.TypeCheck.Monad( InferM, recordError, getTVars )+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)@@ -28,6 +29,7 @@ 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@@ -48,13 +50,13 @@  -- | Check for duplicate and recursive type synonyms. -- Returns the type-synonyms in dependency order.-orderTyDecls :: [TyDecl] -> InferM [TyDecl]+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) ]-     concat `fmap` mapM check ordered+     runExceptionT (concat `fmap` mapM check ordered)    where   toMap vs ty@(PT p _) =@@ -81,7 +83,7 @@                        boundNamesSet vs $                        boundNames (map P.tpName as) $                        Set.unions $-                       map (tnamesT . P.value) fs+                       map (tnamesT . snd) (recordElements fs)                   )         }     )@@ -112,17 +114,12 @@   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) =-    do recordError (RecursiveTypeDecls (map getN xs))-       return [] -- XXX: This is likely to cause fake errors for missing-                 -- type synonyms. We could avoid this by, for example, checking-                 -- for recursive synonym errors, when looking up tycons.--+  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)]
src/Cryptol/TypeCheck/Error.hs view
@@ -117,6 +117,10 @@                 -- ^ Too many positional type arguments, in an explicit                 -- type instantiation +              | BadParameterKind TParam Kind+                -- ^ Kind other than `*` or `#` given to parameter of+                --   type synonym, newtype, function signature, etc.+               | CannotMixPositionalAndNamedTypeParams                | UndefinedTypeParameter (Located Ident)@@ -128,6 +132,9 @@                 --   but we know it must be at least as large as the given type                 --   (or unconstrained, if Nothing). +              | BareTypeApp+                -- ^ Bare expression of the form `{_}+               | UndefinedExistVar Name               | TypeShadowing String Name String               | MissingModTParam (Located Ident)@@ -139,6 +146,7 @@ errorImportance :: Error -> Int errorImportance err =   case err of+    BareTypeApp                                      -> 11 -- basically a parse error     KindMismatch {}                                  -> 10     TyVarWithParams {}                               -> 9     TypeMismatch {}                                  -> 8@@ -151,7 +159,7 @@     MissingModTParam {}                              -> 10     MissingModVParam {}                              -> 10 -+    BadParameterKind{}                               -> 9     CannotMixPositionalAndNamedTypeParams {}         -> 8     TooManyTypeParams {}                             -> 8     TooFewTyParams {}                                -> 8@@ -180,6 +188,7 @@   + instance TVars Warning where   apSubst su warn =     case warn of@@ -215,10 +224,12 @@       TooManyPositionalTypeParams -> err       CannotMixPositionalAndNamedTypeParams -> err +      BadParameterKind{} -> err       UndefinedTypeParameter {} -> err       RepeatedTypeParameter {} -> err       AmbiguousSize x t -> AmbiguousSize x !$ (apSubst su t) +      BareTypeApp -> err        UndefinedExistVar {} -> err       TypeShadowing {}     -> err@@ -249,7 +260,10 @@       UndefinedTypeParameter {}             -> Set.empty       RepeatedTypeParameter {}              -> Set.empty       AmbiguousSize _ t -> fvs t+      BadParameterKind tp _ -> Set.singleton (TVBound tp) +      BareTypeApp -> Set.empty+       UndefinedExistVar {} -> Set.empty       TypeShadowing {}     -> Set.empty       MissingModTParam {}  -> Set.empty@@ -378,9 +392,15 @@                , "When checking" <+> pp src                ] +      BadParameterKind tp k ->+        addTVarsDescsAfter names err $+        vcat [ "Illegal kind assigned to type variable:" <+> ppWithNames names tp+             , "Unexpected:" <+> pp k+             ]+       TooManyPositionalTypeParams ->         addTVarsDescsAfter names err $-        "Too many positional type-parameters in explicit type application"+        "Too many positional type-parameters in explicit type application."        CannotMixPositionalAndNamedTypeParams ->         addTVarsDescsAfter names err $@@ -403,6 +423,10 @@                  Nothing -> empty          in addTVarsDescsAfter names err ("Ambiguous numeric type:" <+> pp (tvarDesc x) $$ sizeMsg) +      BareTypeApp ->+        "Unexpected bare type application." $$+        "Perhaps you meant `( ... ) instead."+       UndefinedExistVar x -> "Undefined type" <+> quotes (pp x)       TypeShadowing this new that ->         "Type" <+> text this <+> quotes (pp new) <+>@@ -475,7 +499,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@@ -513,6 +537,10 @@             let doc2 = tys !! 1             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 <> "."))+           PFLiteral ->             case ts of               ~[m,n,_r,_a] ->@@ -544,7 +572,7 @@    {- XXX: Currently we pick the names based on the unique of the variable:      smaller uniques get an earlier name (e.g., 100 might get `a` and 200 `b`)-     This may still lead to changes in the names if the uniques got reordred+     This may still lead to changes in the names if the uniques got reordered      for some reason.  A more stable approach might be to order the variables      on their location in the error/warning, but that's quite a bit more code      so for now we just go with the simple approximation. -}@@ -570,4 +598,3 @@   variant n x = if n == 0 then x else x ++ suff n    variants roots = [ variant n r | n <- [ 0 .. ], r <- roots ]-
src/Cryptol/TypeCheck/Infer.hs view
@@ -169,7 +169,9 @@          -- XXX: Is there a scoping issue here?  I think not, but check.      P.ELocated e r ->-      inRange r (appTys e ts tGoal)+      do e' <- inRange r (appTys e ts tGoal)+         cs <- getCallStacks+         if cs then pure (ELocated r e') else pure e'      P.ENeg        {} -> mono     P.EComplement {} -> mono@@ -181,6 +183,7 @@     P.ESel      {} -> mono     P.EList     {} -> mono     P.EFromTo   {} -> mono+    P.EFromToLessThan {} -> mono     P.EInfFrom  {} -> mono     P.EComp     {} -> mono     P.EApp      {} -> mono@@ -292,6 +295,20 @@          es' <- mapM checkElem es          return (EList es' a) +    P.EFromToLessThan t1 t2 mety ->+      do l <- curRange+         let fs0 =+               case mety of+                 Just ety -> [("a", ety)]+                 Nothing  -> []+         let fs = [("first", t1), ("bound", t2)] ++ fs0+         prim <- mkPrim "fromToLessThan"+         let e' = P.EAppT prim+                  [ P.NamedInst P.Named { name = Located l (packIdent x), value = y }+                  | (x,y) <- fs+                  ]+         checkE e' tGoal+     P.EFromTo t1 mbt2 t3 mety ->       do l <- curRange          let fs0 =@@ -366,9 +383,12 @@                    P.Named { name = Located l (packIdent "val")                            , value = t }]) tGoal -    P.EFun ps e -> checkFun Nothing ps e tGoal+    P.EFun desc ps e -> checkFun desc ps e tGoal -    P.ELocated e r  -> inRange r (checkE e tGoal)+    P.ELocated e r  ->+      do e' <- inRange r (checkE e tGoal)+         cs <- getCallStacks+         if cs then pure (ELocated r e') else pure e'      P.ESplit e ->       do prim <- mkPrim "splitAt"@@ -388,7 +408,7 @@     Nothing ->       do r <- newParamName (packIdent "r")          let p  = P.PVar Located { srcRange = nameLoc r, thing = r }-             fe = P.EFun [p] (P.EUpd (Just (P.EVar r)) fs)+             fe = P.EFun P.emptyFunDesc [p] (P.EUpd (Just (P.EVar r)) fs)          checkE fe tGoal      Just e ->@@ -561,11 +581,11 @@   checkFun ::-  Maybe 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 fun ps e tGoal =+checkFun (P.FunDesc fun offset) ps e tGoal =   inNewScope $-  do let descs = [ TypeOfArg (ArgDescr fun (Just n)) | n <- [ 1 :: Int .. ] ]+  do let descs = [ TypeOfArg (ArgDescr fun (Just n)) | n <- [ 1 + offset .. ] ]       (tys,tRes) <- expectFun fun (length ps) tGoal      largs      <- sequence (zipWith checkP ps (zipWith WithSource tys descs))@@ -826,8 +846,13 @@           * and vars in the inferred types that do not appear anywhere else. -}      let as   = sortBy numFst               $ as0 ++ Set.toList (Set.difference inSigs asmpVs)-         asPs = [ TParam { tpUnique = x, tpKind = k, tpFlav = TPOther Nothing-                         , tpInfo = i  } | TVFree x k _ i <- as ]+         asPs = [ TParam { tpUnique = x+                         , tpKind   = k+                         , tpFlav   = TPUnifyVar+                         , tpInfo   = i+                         }+                | TVFree x k _ i <- as+                ]       {- Finally, we replace free variables with bound ones, and fix-up         the definitions as needed to reflect that we are now working@@ -866,7 +891,7 @@     P.DExpr e ->       do let nm = thing (P.bName b)          let tGoal = WithSource t (DefinitionOf nm)-         e1 <- checkFun (Just nm) (P.bParams b) e tGoal+         e1 <- checkFun (P.FunDesc (Just nm) 0) (P.bParams b) e tGoal          let f = thing (P.bName b)          return Decl { dName = f                      , dSignature = Forall [] [] t@@ -898,7 +923,7 @@   do (e1,cs0) <- collectGoals $                 do let nm = thing (P.bName b)                        tGoal = WithSource t0 (DefinitionOf nm)-                   e1 <- checkFun (Just nm) (P.bParams b) e0 tGoal+                   e1 <- checkFun (P.FunDesc (Just nm) 0) (P.bParams b) e0 tGoal                    addGoals validSchema                    () <- simplifyAllConstraints  -- XXX: using `asmps` also?                    return e1@@ -941,8 +966,10 @@         }  inferDs :: FromDecl d => [d] -> ([DeclGroup] -> InferM a) -> InferM a-inferDs ds continue = checkTyDecls =<< orderTyDecls (mapMaybe toTyDecl ds)+inferDs ds continue = either onErr checkTyDecls =<< orderTyDecls (mapMaybe toTyDecl ds)   where+  onErr err = recordError err >> continue []+   isTopLevel = isTopDecl (head ds)    checkTyDecls (AT t mbD : ts) =
src/Cryptol/TypeCheck/InferTypes.hs view
@@ -47,6 +47,7 @@     -- ^ Look for the solver prelude in these locations.   } deriving (Show, Generic, NFData) + -- | The types of variables in the environment. data VarType = ExtVar Schema                -- ^ Known type@@ -66,6 +67,10 @@    , literalGoals :: Map TVar LitGoal     -- ^ An entry @(a,t)@ corresponds to @Literal t a@.++  , literalLessThanGoals :: Map TVar LitGoal+    -- ^ An entry @(a,t)@ corresponds to @LiteralLessThan t a@.+   } deriving (Show)  -- | This abuses the type 'Goal' a bit. The 'goal' field contains@@ -84,15 +89,35 @@      return (a, g { goal = tn })  +litLessThanGoalToGoal :: (TVar,LitGoal) -> Goal+litLessThanGoalToGoal (a,g) = g { goal = pLiteralLessThan (goal g) (TVar a) } +goalToLitLessThanGoal :: Goal -> Maybe (TVar,LitGoal)+goalToLitLessThanGoal g =+  do (tn,a) <- matchMaybe $ do (tn,b) <- aLiteralLessThan (goal g)+                               a      <- aTVar b+                               return (tn,a)+     return (a, g { goal = tn })++ emptyGoals :: Goals-emptyGoals  = Goals { goalSet = Set.empty, saturatedPropSet = Set.empty, literalGoals = Map.empty }+emptyGoals  =+  Goals+  { goalSet = Set.empty+  , saturatedPropSet = Set.empty+  , literalGoals = Map.empty+  , literalLessThanGoals = Map.empty+  }  nullGoals :: Goals -> Bool-nullGoals gs = Set.null (goalSet gs) && Map.null (literalGoals gs)+nullGoals gs =+  Set.null (goalSet gs) &&+  Map.null (literalGoals gs) &&+  Map.null (literalLessThanGoals gs)  fromGoals :: Goals -> [Goal] fromGoals gs = map litGoalToGoal (Map.toList (literalGoals gs)) +++               map litLessThanGoalToGoal (Map.toList (literalLessThanGoals gs)) ++                Set.toList (goalSet gs)  goalsFromList :: [Goal] -> Goals@@ -106,6 +131,11 @@        let jn g1 g2 = g1 { goal = tMax (goal g1) (goal g2) } in        gls { literalGoals = Map.insertWith jn a newG (literalGoals gls)            , saturatedPropSet = Set.insert (pFin (TVar a)) (saturatedPropSet gls)+           }++  | Just (a,newG) <- goalToLitLessThanGoal g =+       let jn g1 g2 = g1 { goal = tMax (goal g1) (goal g2) } in+       gls { literalLessThanGoals = Map.insertWith jn a newG (literalLessThanGoals gls)            }    -- If the goal is already implied by some other goal, skip it
src/Cryptol/TypeCheck/Instantiate.hs view
@@ -102,9 +102,9 @@     where     src = case drop (n-1) {- count from 1 -} as of             p:_ ->-              case tpFlav p of-                TPOther (Just a) -> TypeParamInstNamed nm (nameIdent a)-                _                -> TypeParamInstPos nm n+              case tpName p of+                Just a -> TypeParamInstNamed nm (nameIdent a)+                _      -> TypeParamInstPos nm n             _ -> panic "instantiateWithPos"                     [ "Invalid parameter index", show n, show as ] 
src/Cryptol/TypeCheck/Kind.hs view
@@ -20,7 +20,6 @@   ) where  import qualified Cryptol.Parser.AST as P-import           Cryptol.Parser.AST (Named(..)) import           Cryptol.Parser.Position import           Cryptol.TypeCheck.AST import           Cryptol.TypeCheck.Error@@ -37,7 +36,7 @@ import           Data.Maybe(fromMaybe) import           Data.Function(on) import           Data.Text (Text)-import           Control.Monad(unless,forM,when)+import           Control.Monad(unless,when)   @@ -114,11 +113,8 @@   do ((as1,fs1),gs) <- collectGoals $        inRange (srcRange x) $        do r <- withTParams NoWildCards newtypeParam as $-               forM fs $ \field ->-                 let n = name field-                 in kInRange (srcRange n) $-                    do t1 <- doCheckType (value field) (Just KType)-                       return (thing n, t1)+               flip traverseRecordMap fs $ \_n (rng,f) ->+                 kInRange rng $ doCheckType f (Just KType)           simplifyAllConstraints           return r @@ -132,7 +128,7 @@ checkPrimType :: P.PrimType Name -> Maybe Text -> InferM AbstractType checkPrimType p mbD =   do let (as,cs) = P.primTCts p-     (as',cs') <- withTParams NoWildCards (TPOther . Just) as $+     (as',cs') <- withTParams NoWildCards TPPrimParam as $                     mapM checkProp cs      pure AbstractType { atName = thing (P.primTName p)                        , atKind = cvtK (thing (P.primTKind p))@@ -265,10 +261,13 @@        checkKind (TUser x ts1 t1) k k1    checkNewTypeUse nt =-    do let tc = newtypeTyCon nt-       (ts1,_) <- appTy ts (kindOf tc)-       ts2 <- checkParams (ntParams nt) ts1-       return (TCon tc ts2)+    do (ts1,k1) <- appTy ts (kindOf nt)+       let as = ntParams nt+       ts2 <- checkParams as ts1+       let su = zip as ts2+       ps1 <- mapM (`kInstantiateT` su) (ntConstraints nt)+       kNewGoals (CtPartialTypeFun (ntName nt)) ps1+       checkKind (TNewtype nt ts2) k k1    checkAbstractTypeUse absT =     do let tc   = abstractTypeTC absT@@ -388,8 +387,8 @@      P.TInfix t x _ u-> doCheckType (P.TUser (thing x) [t, u]) k -    P.TTyApp _fs    -> panic "doCheckType"-                         ["TTyApp found when kind checking, but it should have been eliminated already"]+    P.TTyApp _fs    -> do kRecordError BareTypeApp+                          kNewType TypeWildCard KNum    where   checkF _nm (rng,v) = kInRange rng $ doCheckType v (Just KType)
src/Cryptol/TypeCheck/Monad.hs view
@@ -74,6 +74,8 @@   , inpMonoBinds :: Bool              -- ^ Should local bindings without                                       --   signatures be monomorphized? +  , inpCallStacks :: Bool             -- ^ Are we tracking call stacks?+   , inpSolverConfig :: SolverConfig   -- ^ Options for the constraint solver   , inpSearchPath :: [FilePath]     -- ^ Where to look for Cryptol theory file.@@ -83,8 +85,9 @@     -- identifier (e.g., @number@).    , inpSupply :: !Supply              -- ^ The supply for fresh name generation-  } deriving Show +  , inpSolver :: SMT.Solver           -- ^ Solver connection for typechecking+  }  -- | This is used for generating various names. data NameSeeds = NameSeeds@@ -114,7 +117,7 @@                  io $ modifyIORef' iSolveCounter (+1)  runInferM :: TVars a => InferInput -> InferM a -> IO (InferOutput a)-runInferM info (IM m) = SMT.withSolver (inpSolverConfig info) $ \solver ->+runInferM info (IM m) =   do counter <- newIORef 0      rec ro <- return RO { iRange     = inpRange info                          , iVars          = Map.map ExtVar (inpVars info)@@ -128,7 +131,8 @@                           , iSolvedHasLazy = iSolvedHas finalRW     -- RECURSION                          , iMonoBinds     = inpMonoBinds info-                         , iSolver        = solver+                         , iCallStacks    = inpCallStacks info+                         , iSolver        = inpSolver info                          , iPrimNames     = inpPrimNames info                          , iSolveCounter  = counter                          }@@ -232,6 +236,10 @@     -- in where-blocks will never be generalized. Bindings with type     -- signatures, and all bindings at top level are unaffected. +  , iCallStacks :: Bool+    -- ^ When this flag is true, retain source location information+    --   in typechecked terms+   , iSolver :: SMT.Solver    , iPrimNames :: !PrimMap@@ -475,22 +483,54 @@                      in (TVFree x k vs msg, s { seedTVar = x + 1 })  +-- | Check that the given "flavor" of parameter is allowed to+--   have the given type, and raise an error if not+checkParamKind :: TParam -> TPFlavor -> Kind -> InferM () +checkParamKind tp flav k =+    case flav of+      TPModParam _     -> return () -- All kinds allowed as module parameters+      TPPropSynParam _ -> starOrHashOrProp+      TPTySynParam _   -> starOrHash+      TPSchemaParam _  -> starOrHash+      TPNewtypeParam _ -> starOrHash+      TPPrimParam _    -> starOrHash+      TPUnifyVar       -> starOrHash++  where+    starOrHashOrProp =+      case k of+        KNum  -> return ()+        KType -> return ()+        KProp -> return ()+        _ -> recordError (BadParameterKind tp k)++    starOrHash =+      case k of+        KNum  -> return ()+        KType -> return ()+        _ -> recordError (BadParameterKind tp k)++ -- | Generate a new free type variable. newTParam :: P.TParam Name -> TPFlavor -> Kind -> InferM TParam-newTParam nm flav k = newName $ \s ->-  let x = seedTVar s-  in (TParam { tpUnique = x-            , tpKind   = k-            , tpFlav   = flav-            , tpInfo   = desc-            }-     , s { seedTVar = x + 1 })-  where desc = TVarInfo { tvarDesc = TVFromSignature (P.tpName nm)-                        , tvarSource = fromMaybe emptyRange (P.tpRange nm)+newTParam nm flav k =+  do let desc = TVarInfo { tvarDesc = TVFromSignature (P.tpName nm)+                         , tvarSource = fromMaybe emptyRange (P.tpRange nm)+                         }+     tp <- newName $ \s ->+             let x = seedTVar s+             in (TParam { tpUnique = x+                        , tpKind   = k+                        , tpFlav   = flav+                        , tpInfo   = desc                         }+                , s { seedTVar = x + 1 }) +     checkParamKind tp flav k+     return tp + -- | Generate an unknown type.  The doc is a note about what is this type about. newType :: TypeSource -> Kind -> InferM Type newType src k = TVar `fmap` newTVar src k@@ -692,6 +732,9 @@ getMonoBinds :: InferM Bool getMonoBinds  = IM (asks iMonoBinds) +getCallStacks :: InferM Bool+getCallStacks = IM (asks iCallStacks)+ {- | We disallow shadowing between type synonyms and type variables because it is confusing.  As a bonus, in the implementation we don't need to worry about where we lookup things (i.e., in the variable or@@ -942,5 +985,3 @@  kInInferM :: InferM a -> KindM a kInInferM m = KM $ lift $ lift m--
src/Cryptol/TypeCheck/Parseable.hs view
@@ -31,6 +31,7 @@   showParseable :: t -> Doc  instance ShowParseable Expr where+  showParseable (ELocated _ e) = showParseable e -- TODO? emit range information   showParseable (EList es _) = parens (text "EList" <+> showParseable es)   showParseable (ETuple es) = parens (text "ETuple" <+> showParseable es)   showParseable (ERec ides) = parens (text "ERec" <+> showParseable (canonicalFields ides))
src/Cryptol/TypeCheck/Sanity.hs view
@@ -15,7 +15,7 @@   ) where  -import Cryptol.Parser.Position(thing)+import Cryptol.Parser.Position(thing,Range,emptyRange) import Cryptol.TypeCheck.AST import Cryptol.TypeCheck.Subst (apSubst, singleTParamSubst) import Cryptol.TypeCheck.Monad(InferInput(..))@@ -31,15 +31,15 @@ import qualified Data.Map as Map  -tcExpr :: InferInput -> Expr -> Either Error (Schema, [ ProofObligation ])+tcExpr :: InferInput -> Expr -> Either (Range, Error) (Schema, [ ProofObligation ]) tcExpr env e = runTcM env (exprSchema e) -tcDecls :: InferInput -> [DeclGroup] -> Either Error [ ProofObligation ]+tcDecls :: InferInput -> [DeclGroup] -> Either (Range, Error) [ ProofObligation ] tcDecls env ds0 = case runTcM env (checkDecls ds0) of                     Left err     -> Left err                     Right (_,ps) -> Right ps -tcModule :: InferInput -> Module -> Either Error [ ProofObligation ]+tcModule :: InferInput -> Module -> Either (Range, Error) [ ProofObligation ] tcModule env m = case runTcM env check of                    Left err -> Left err                    Right (_,ps) -> Right ps@@ -68,6 +68,10 @@       do ks <- mapM checkType ts          checkKind (kindOf tc) ks +    TNewtype nt ts ->+      do ks <- mapM checkType ts+         checkKind (kindOf nt) ks+     TVar tv -> lookupTVar tv      TRec fs ->@@ -143,6 +147,8 @@ exprSchema expr =   case expr of +    ELocated rng t -> withRange rng (exprSchema t)+     EList es t ->       do checkTypeIs KType t          forM_ es $ \e ->@@ -367,6 +373,12 @@                                | tc1 == tc2 -> goMany ts1 ts2                             _ -> err +         TNewtype nt1 ts1 ->+            case other of+              TNewtype nt2 ts2+                | nt1 == nt2 -> goMany ts1 ts2+              _ -> err+          TRec fs ->            case other of              TRec gs ->@@ -444,6 +456,7 @@ data RO = RO   { roTVars   :: Map Int TParam   , roAsmps   :: [Prop]+  , roRange   :: Range   , roVars    :: Map Name Schema   } @@ -453,7 +466,7 @@   { woProofObligations :: [ProofObligation]   } -newtype TcM a = TcM (ReaderT RO (ExceptionT Error (StateT RW Id)) a)+newtype TcM a = TcM (ReaderT RO (ExceptionT (Range, Error) (StateT RW Id)) a)  instance Functor TcM where   fmap = liftM@@ -468,7 +481,7 @@                         let TcM m1 = f a                         m1) -runTcM :: InferInput -> TcM a -> Either Error (a, [ProofObligation])+runTcM :: InferInput -> TcM a -> Either (Range, Error) (a, [ProofObligation]) runTcM env (TcM m) =   case runM m ro rw of     (Left err, _) -> Left err@@ -478,6 +491,7 @@                                       | tp <- Map.elems (inpParamTypes env)                                       , let x = mtpParam tp ]           , roAsmps = map thing (inpParamConstraints env)+          , roRange = emptyRange           , roVars  = Map.union                         (fmap mvpType (inpParamFuns env))                         (inpVars env)@@ -511,12 +525,19 @@     deriving Show  reportError :: Error -> TcM a-reportError e = TcM (raise e)+reportError e = TcM $+  do ro <- ask+     raise (roRange ro, e)  withTVar :: TParam -> TcM a -> TcM a withTVar a (TcM m) = TcM $   do ro <- ask      local ro { roTVars = Map.insert (tpUnique a) a (roTVars ro) } m++withRange :: Range -> TcM a -> TcM a+withRange rng (TcM m) = TcM $+  do ro <- ask+     local ro { roRange = rng } m  withAsmp :: Prop -> TcM a -> TcM a withAsmp p (TcM m) = TcM $
src/Cryptol/TypeCheck/SimpType.hs view
@@ -19,6 +19,7 @@         | otherwise -> go t       TVar _        -> ty       TRec xs       -> TRec (fmap go xs)+      TNewtype nt xs -> TNewtype nt (map go xs)       TCon tc ts    -> tCon tc (map go ts)  tRebuild :: Type -> Type
src/Cryptol/TypeCheck/SimpleSolver.hs view
@@ -11,6 +11,7 @@   , solveIntegralInst, solveFieldInst, solveRoundInst   , solveEqInst, solveCmpInst, solveSignedCmpInst   , solveLiteralInst+  , solveLiteralLessThanInst   , solveValidFloat, solveFLiteralInst   ) @@ -55,6 +56,7 @@     TCon (PC PCmp)   [ty]      -> solveCmpInst ty     TCon (PC PSignedCmp) [ty]  -> solveSignedCmpInst ty     TCon (PC PLiteral) [t1,t2] -> solveLiteralInst t1 t2+    TCon (PC PLiteralLessThan) [t1,t2] -> solveLiteralLessThanInst t1 t2     TCon (PC PFLiteral) [t1,t2,t3,t4] -> solveFLiteralInst t1 t2 t3 t4      TCon (PC PValidFloat) [t1,t2] -> solveValidFloat t1 t2
src/Cryptol/TypeCheck/Solver/Class.hs view
@@ -20,14 +20,15 @@   , solveCmpInst   , solveSignedCmpInst   , solveLiteralInst+  , solveLiteralLessThanInst   , solveFLiteralInst   , solveValidFloat   ) where  import qualified LibBF as FP -import Cryptol.TypeCheck.Type-import Cryptol.TypeCheck.SimpType (tAdd,tWidth)+import Cryptol.TypeCheck.Type hiding (tSub)+import Cryptol.TypeCheck.SimpType (tAdd,tSub,tWidth,tMax) import Cryptol.TypeCheck.Solver.Types import Cryptol.Utils.RecordMap @@ -99,6 +100,9 @@   -- (Zero a, Zero b) => Zero { x1 : a, x2 : b }   TRec fs -> SolvedIf [ pZero ety | ety <- recordElements fs ] +  -- Zero <newtype> -> fails+  TNewtype{} -> Unsolvable+   _ -> Unsolved  -- | Solve a Logic constraint by instance, if possible.@@ -135,6 +139,9 @@   -- (Logic a, Logic b) => Logic { x1 : a, x2 : b }   TRec fs -> SolvedIf [ pLogic ety | ety <- recordElements fs ] +  -- Logic <newtype> -> fails+  TNewtype{} -> Unsolvable+   _ -> Unsolved  @@ -172,6 +179,9 @@   -- (Ring a, Ring b) => Ring { x1 : a, x2 : b }   TRec fs -> SolvedIf [ pRing ety | ety <- recordElements fs ] +  -- Ring <newtype> -> fails+  TNewtype{} -> Unsolvable+   _ -> Unsolved  @@ -256,6 +266,9 @@   -- Field {x : a, y : b, ...} fails   TRec _ -> Unsolvable +  -- Field <newtype> -> fails+  TNewtype{} -> Unsolvable+   _ -> Unsolved  @@ -295,6 +308,9 @@   -- Round {x : a, y : b, ...} fails   TRec _ -> Unsolvable +  -- Round <newtype> -> fails+  TNewtype{} -> Unsolvable+   _ -> Unsolved  @@ -333,6 +349,9 @@   -- (Eq a, Eq b) => Eq { x:a, y:b }   TRec fs -> SolvedIf [ pEq e | e <- recordElements fs ] +  -- Eq <newtype> -> fails+  TNewtype{} -> Unsolvable+   _ -> Unsolved  @@ -370,6 +389,9 @@   -- (Cmp a, Cmp b) => Cmp { x:a, y:b }   TRec fs -> SolvedIf [ pCmp e | e <- recordElements fs ] +  -- Cmp <newtype> -> fails+  TNewtype{} -> Unsolvable+   _ -> Unsolved  @@ -422,6 +444,9 @@   -- (SignedCmp a, SignedCmp b) => SignedCmp { x:a, y:b }   TRec fs -> SolvedIf [ pSignedCmp e | e <- recordElements fs ] +  -- SignedCmp <newtype> -> fails+  TNewtype{} -> Unsolvable+   _ -> Unsolved  @@ -459,6 +484,7 @@        _ -> Unsolvable + -- | Solve Literal constraints. solveLiteralInst :: Type -> Type -> Solved solveLiteralInst val ty@@ -490,12 +516,11 @@         | otherwise -> Unsolved  -       -- (fin val, fin m, m >= val + 1) => Literal val (Z m)       TCon (TC TCIntMod) [modulus] ->         SolvedIf [ pFin val, pFin modulus, modulus >== tAdd val tOne ] -      -- (fin bits, bits => width n) => Literal n [bits]+      -- (fin bits, bits >= width n) => Literal n [bits]       TCon (TC TCSeq) [bits, elTy]         | TCon (TC TCBit) [] <- ety ->             SolvedIf [ pFin val, pFin bits, bits >== tWidth val ]@@ -507,3 +532,50 @@       _ -> Unsolvable  +-- | Solve Literal constraints.+solveLiteralLessThanInst :: Type -> Type -> Solved+solveLiteralLessThanInst val ty+  | TCon (TError {}) _ <- tNoUser val = Unsolvable+  | otherwise =+    case tNoUser ty of++      -- Literal n Error -> fails+      TCon (TError {}) _ -> Unsolvable++      -- (2 >= val) => LiteralLessThan val Bit+      TCon (TC TCBit) [] -> SolvedIf [ tTwo >== val ]++      -- LiteralLessThan val Integer+      TCon (TC TCInteger) [] -> SolvedIf [ ]++      -- LiteralLessThan val Rational+      TCon (TC TCRational) [] -> SolvedIf [ ]++      -- ValidFloat e p => LiteralLessThan val (Float e p)   if `val-1` is representable+      -- RWD Should we remove this instance for floats?+      TCon (TC TCFloat) [e, p]+        | Just n <- tIsNum val+        , n > 0+        , Just opts  <- knownSupportedFloat e p ->+          let bf = FP.bfFromInteger (n-1)+          in case FP.bfRoundFloat opts bf of+               (bf1,FP.Ok) | bf == bf1 -> SolvedIf []+               _ -> Unsolvable++        | otherwise -> Unsolved++      -- (fin val, fin m, m >= val) => LiteralLessThan val (Z m)+      TCon (TC TCIntMod) [modulus] ->+        SolvedIf [ pFin val, pFin modulus, modulus >== val ]++      -- (fin bits, bits >= lg2 n) => LiteralLessThan n [bits]+      TCon (TC TCSeq) [bits, elTy]+        | TCon (TC TCBit) [] <- ety ->+            SolvedIf [ pFin val, pFin bits, bits >== tWidth val' ]+        | TVar _ <- ety -> Unsolved+        where ety  = tNoUser elTy+              val' = tSub (tMax val tOne) tOne++      TVar _ -> Unsolved++      _ -> Unsolvable
src/Cryptol/TypeCheck/Solver/Improve.hs view
@@ -45,6 +45,8 @@   improveLit impSkol prop   -- XXX: others +-- Whenever we have `Literal n [m]a`,+-- we can learn that `a = Bit` improveLit :: Bool -> Prop -> Match (Subst, [Prop]) improveLit impSkol prop =   do (_,t) <- aLiteral prop@@ -53,7 +55,6 @@      unless impSkol $ guard (isFreeTV a)      let su = uncheckedSingleSubst a tBit      return (su, [])-   -- | Improvements from equality constraints.
src/Cryptol/TypeCheck/Solver/SMT.hs view
@@ -16,6 +16,8 @@   ( -- * Setup     Solver   , withSolver+  , startSolver+  , stopSolver   , isNumeric      -- * Debugging@@ -65,21 +67,20 @@     -- ^ For debugging   } --- | Execute a computation with a fresh solver instance.-withSolver :: SolverConfig -> (Solver -> IO a) -> IO a-withSolver SolverConfig{ .. } =-     bracket-       (do logger <- if solverVerbose > 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-           return sol)-       (\s -> void $ SMT.stop (solver s))+-- | Start a fresh solver instance+startSolver :: SolverConfig -> IO Solver+startSolver SolverConfig { .. } =+   do logger <- if solverVerbose > 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+      return sol+   where   quietLogger = SMT.Logger { SMT.logMessage = \_ -> return ()                            , SMT.logLevel   = return 0@@ -88,7 +89,14 @@                            , SMT.logUntab   = return ()                            } +-- | Shut down a solver instance+stopSolver :: Solver -> IO ()+stopSolver s = void $ SMT.stop (solver s) +-- | Execute a computation with a fresh solver instance.+withSolver :: SolverConfig -> (Solver -> IO a) -> IO a+withSolver cfg = bracket (startSolver cfg) stopSolver+ -- | Load the definitions used for type checking. loadTcPrelude :: Solver -> [FilePath] {- ^ Search in this paths -} -> IO () loadTcPrelude s [] = loadString s cryptolTcContents@@ -388,8 +396,3 @@   mk tvs f (x,y,z) = SMT.fun f [ toSMT tvs x, toSMT tvs y, toSMT tvs z ]  -------------------------------------------------------------------------------------
src/Cryptol/TypeCheck/Solver/Selector.hs view
@@ -10,7 +10,7 @@  import Cryptol.TypeCheck.AST import Cryptol.TypeCheck.InferTypes-import Cryptol.TypeCheck.Monad( InferM, unify, newGoals, lookupNewtype+import Cryptol.TypeCheck.Monad( InferM, unify, newGoals                               , newType, applySubst, solveHasGoal                               , newParamName                               )@@ -66,21 +66,18 @@      (RecordSel l _, ty) ->       case ty of-        TRec fs  -> return (lookupField l fs)+        TRec fs -> return (lookupField l fs)+        TNewtype nt ts ->+          case lookupField l (ntFields nt) of+            Nothing -> return Nothing+            Just t ->+              do let su = listParamSubst (zip (ntParams nt) ts)+                 newGoals (CtPartialTypeFun (ntName nt))+                   $ apSubst su $ ntConstraints nt+                 return $ Just $ apSubst su t+         TCon (TC TCSeq) [len,el] -> liftSeq len el         TCon (TC TCFun) [t1,t2]  -> liftFun t1 t2-        TCon (TC (TCNewtype (UserTC x _))) ts ->-          do mb <- lookupNewtype x-             case mb of-               Nothing -> return Nothing-               Just nt ->-                 case lookup l (ntFields nt) of-                   Nothing -> return Nothing-                   Just t  ->-                     do let su = listParamSubst (zip (ntParams nt) ts)-                        newGoals (CtPartialTypeFun x)-                          $ apSubst su $ ntConstraints nt-                        return $ Just $ apSubst su t         _ -> return Nothing      (TupleSel n _, ty) ->
src/Cryptol/TypeCheck/Solver/Utils.hs view
@@ -22,6 +22,7 @@   go ty = case ty of             TVar x      -> return (x, tNum (0::Int))             TRec {}     -> []+            TNewtype{}  -> []             TUser _ _ t -> go t             TCon (TF TCAdd) [t1,t2] ->               do (a,yes) <- go t1@@ -45,6 +46,7 @@   case ty of     TVar {}     -> Nothing     TRec {}     -> Nothing+    TNewtype{}  -> Nothing     TUser _ _ t -> splitConstSummand t     TCon (TF TCAdd) [t1,t2] ->       do (k,t1') <- splitConstSummand t1@@ -63,6 +65,7 @@   case ty of     TVar {}     -> Nothing     TRec {}     -> Nothing+    TNewtype{}  -> Nothing     TUser _ _ t -> splitConstFactor t     TCon (TF TCMul) [t1,t2] ->       do (k,t1') <- splitConstFactor t1
src/Cryptol/TypeCheck/Subst.hs view
@@ -240,7 +240,8 @@       do (ts1, t1) <- anyJust2 (anyJust (apSubstMaybe su)) (apSubstMaybe su) (ts, t)          Just (TUser f ts1 t1) -    TRec fs       -> TRec `fmap` (anyJust (apSubstMaybe su) fs)+    TRec fs -> TRec `fmap` (anyJust (apSubstMaybe su) fs)+    TNewtype nt ts -> TNewtype nt `fmap` anyJust (apSubstMaybe su) ts     TVar x -> applySubstToVar su x  lookupSubst :: TVar -> Subst -> Maybe Type@@ -315,6 +316,7 @@     tm' = TM { tvar = Map.fromList   vars              , tcon = fmap (lgo merge atNode) tcon              , trec = fmap (lgo merge atNode) trec+             , tnewtype = fmap (lgo merge atNode) tnewtype              }      -- partition out variables that have been replaced with more specific types@@ -348,6 +350,7 @@     where     go expr =       case expr of+        ELocated r e  -> ELocated r !$ (go e)         EApp e1 e2    -> EApp !$ (go e1) !$ (go e2)         EAbs x t e1   -> EAbs x !$ (apSubst su t) !$ (go e1)         ETAbs a e     -> ETAbs a !$ (go e)
src/Cryptol/TypeCheck/TCon.hs view
@@ -80,6 +80,7 @@     , "Cmp"               ~> PC PCmp     , "SignedCmp"         ~> PC PSignedCmp     , "Literal"           ~> PC PLiteral+    , "LiteralLessThan"   ~> PC PLiteralLessThan     , "FLiteral"          ~> PC PFLiteral      -- Type functions@@ -142,7 +143,6 @@       TCSeq     -> KNum :-> KType :-> KType       TCFun     -> KType :-> KType :-> KType       TCTuple n -> foldr (:->) KType (replicate n KType)-      TCNewtype x -> kindOf x       TCAbstract x -> kindOf x  instance HasKind PC where@@ -164,6 +164,7 @@       PCmp       -> KType :-> KProp       PSignedCmp -> KType :-> KProp       PLiteral   -> KNum :-> KType :-> KProp+      PLiteralLessThan -> KNum :-> KType :-> KProp       PFLiteral  -> KNum :-> KNum :-> KNum :-> KType :-> KProp       PValidFloat -> KNum :-> KNum :-> KProp       PAnd       -> KProp :-> KProp :-> KProp@@ -214,6 +215,7 @@             | PCmp          -- ^ @Cmp _@             | PSignedCmp    -- ^ @SignedCmp _@             | PLiteral      -- ^ @Literal _ _@+            | PLiteralLessThan -- ^ @LiteralLessThan _ _@             | PFLiteral     -- ^ @FLiteral _ _ _@              | PValidFloat   -- ^ @ValidFloat _ _@ constraints on supported@@ -237,7 +239,6 @@             | TCFun                    -- ^ @_ -> _@             | TCTuple Int              -- ^ @(_, _, _)@             | TCAbstract UserTC        -- ^ An abstract type-            | TCNewtype UserTC         -- ^ user-defined, @T@               deriving (Show, Eq, Ord, Generic, NFData)  @@ -316,6 +317,7 @@       PCmp       -> text "Cmp"       PSignedCmp -> text "SignedCmp"       PLiteral   -> text "Literal"+      PLiteralLessThan -> text "LiteralLessThan"       PFLiteral  -> text "FLiteral"       PValidFloat -> text "ValidFloat"       PTrue      -> text "True"@@ -337,7 +339,6 @@       TCTuple 0 -> text "()"       TCTuple 1 -> text "(one tuple?)"       TCTuple n -> parens $ hcat $ replicate (n-1) comma-      TCNewtype u -> pp u       TCAbstract u -> pp u  instance PP UserTC where
src/Cryptol/TypeCheck/Type.hs view
@@ -49,7 +49,12 @@               deriving (Generic, NFData, Show)  data TPFlavor = TPModParam Name-              | TPOther (Maybe Name)+              | TPUnifyVar+              | TPSchemaParam Name+              | TPTySynParam Name+              | TPPropSynParam Name+              | TPNewtypeParam Name+              | TPPrimParam Name               deriving (Generic, NFData, Show)  tMono :: Type -> Schema@@ -62,18 +67,17 @@     _              -> Nothing  - schemaParam :: Name -> TPFlavor-schemaParam x = TPOther (Just x)+schemaParam = TPSchemaParam  tySynParam :: Name -> TPFlavor-tySynParam x = TPOther (Just x)+tySynParam = TPTySynParam  propSynParam :: Name -> TPFlavor-propSynParam x = TPOther (Just x)+propSynParam = TPPropSynParam  newtypeParam :: Name -> TPFlavor-newtypeParam x = TPOther (Just x)+newtypeParam = TPNewtypeParam  modTyParam :: Name -> TPFlavor modTyParam = TPModParam@@ -82,8 +86,13 @@ tpfName :: TPFlavor -> Maybe Name tpfName f =   case f of-    TPModParam x -> Just x-    TPOther x -> x+    TPUnifyVar       -> Nothing+    TPModParam x     -> Just x+    TPSchemaParam x  -> Just x+    TPTySynParam x   -> Just x+    TPPropSynParam x -> Just x+    TPNewtypeParam x -> Just x+    TPPrimParam x    -> Just x  tpName :: TParam -> Maybe Name tpName = tpfName . tpFlav@@ -106,6 +115,9 @@             | TRec !(RecordMap Ident Type)               -- ^ Record type +            | TNewtype !Newtype ![Type]+              -- ^ A newtype+               deriving (Show, Generic, NFData)  @@ -209,11 +221,18 @@ data Newtype  = Newtype { ntName   :: Name                         , ntParams :: [TParam]                         , ntConstraints :: [Prop]-                        , ntFields :: [(Ident,Type)]+                        , ntFields :: RecordMap Ident Type                         , ntDoc :: Maybe Text                         } deriving (Show, Generic, NFData)  +instance Eq Newtype where+  x == y = ntName x == ntName y++instance Ord Newtype where+  compare x y = compare (ntName x) (ntName y)++ -- | Information about an abstract type. data AbstractType = AbstractType   { atName    :: Name@@ -240,6 +259,7 @@       TCon c ts   -> quickApply (kindOf c) ts       TUser _ _ t -> kindOf t       TRec {}     -> KType+      TNewtype{}  -> KType  instance HasKind TySyn where   kindOf ts = foldr (:->) (kindOf (tsDef ts)) (map kindOf (tsParams ts))@@ -270,6 +290,7 @@   TCon x xs == TCon y ys  = x == y && xs == ys   TVar x    == TVar y     = x == y   TRec xs   == TRec ys    = xs == ys+  TNewtype ntx xs == TNewtype nty ys = ntx == nty && xs == ys    _         == _          = False @@ -288,7 +309,10 @@       (_,TCon {})             -> GT        (TRec xs, TRec ys)      -> compare xs ys+      (TRec{}, _)             -> LT+      (_, TRec{})             -> GT +      (TNewtype x xs, TNewtype y ys) -> compare (x,xs) (y,ys)  instance Eq TParam where   x == y = tpUnique x == tpUnique y@@ -332,7 +356,7 @@ newtypeConType :: Newtype -> Schema newtypeConType nt =   Forall as (ntConstraints nt)-    $ TRec (recordFromFields (ntFields nt)) `tFun` TCon (newtypeTyCon nt) (map (TVar . tpVar) as)+    $ TRec (ntFields nt) `tFun` TNewtype nt (map (TVar . tpVar) as)   where   as = ntParams nt @@ -538,6 +562,12 @@                   TCon (PC PLiteral) [t1, t2] -> Just (t1, t2)                   _                           -> Nothing +pIsLiteralLessThan :: Prop -> Maybe (Type, Type)+pIsLiteralLessThan ty =+  case tNoUser ty of+    TCon (PC PLiteralLessThan) [t1, t2] -> Just (t1, t2)+    _                                   -> Nothing+ pIsFLiteral :: Prop -> Maybe (Type,Type,Type,Type) pIsFLiteral ty = case tNoUser ty of                    TCon (PC PFLiteral) [t1,t2,t3,t4] -> Just (t1,t2,t3,t4)@@ -584,6 +614,9 @@ tAbstract :: UserTC -> [Type] -> Type tAbstract u ts = TCon (TC (TCAbstract u)) ts +tNewtype :: Newtype -> [Type] -> Type+tNewtype nt ts = TNewtype nt ts+ tBit     :: Type tBit      = TCon (TC TCBit) [] @@ -620,10 +653,6 @@ tTuple   :: [Type] -> Type tTuple ts = TCon (TC (TCTuple (length ts))) ts -newtypeTyCon :: Newtype -> TCon-newtypeTyCon nt = TC $ TCNewtype $ UserTC (ntName nt) (kindOf nt)-- -- | Make a function type. tFun     :: Type -> Type -> Type tFun a b  = TCon (TC TCFun) [a,b]@@ -725,6 +754,9 @@ pLiteral :: Type -> Type -> Prop pLiteral x y = TCon (PC PLiteral) [x, y] +pLiteralLessThan :: Type -> Type -> Prop+pLiteralLessThan x y = TCon (PC PLiteralLessThan) [x, y]+ -- | Make a greater-than-or-equal-to constraint. (>==) :: Type -> Type -> Prop x >== y = TCon (PC PGeq) [x,y]@@ -801,6 +833,7 @@         TVar x      -> Set.singleton x         TUser _ _ t -> go t         TRec fs     -> fvs (recordElements fs)+        TNewtype _nt ts -> fvs ts  instance FVS a => FVS (Maybe a) where   fvs Nothing  = Set.empty@@ -915,6 +948,7 @@   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                     [ pp l <+> text ":" <+> go 0 t | (l,t) <- displayFields fs ] @@ -972,6 +1006,7 @@           (PCmp, [t1])        -> pp pc <+> go 5 t1           (PSignedCmp, [t1])  -> pp pc <+> go 5 t1           (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) @@ -1011,10 +1046,15 @@       | otherwise =           case tv of             TVBound x ->+              let declNm n = pp n <.> "`" <.> int (tpUnique x) in               case tpFlav x of                 TPModParam n     -> ppPrefixName n-                TPOther (Just n) -> pp n <.> "`" <.> int (tpUnique x)-                _  -> pickTVarName (tpKind x) (tvarDesc (tpInfo x)) (tpUnique x)+                TPUnifyVar       -> pickTVarName (tpKind x) (tvarDesc (tpInfo x)) (tpUnique x)+                TPSchemaParam n  -> declNm n+                TPTySynParam n   -> declNm n+                TPPropSynParam n -> declNm n+                TPNewtypeParam n -> declNm n+                TPPrimParam n    -> declNm n              TVFree x k _ d -> pickTVarName k (tvarDesc d) x 
src/Cryptol/TypeCheck/TypeMap.hs view
@@ -118,14 +118,17 @@ data TypeMap a = TM { tvar :: Map TVar a                     , tcon :: Map TCon    (List TypeMap a)                     , trec :: Map [Ident] (List TypeMap a)+                    , tnewtype :: Map Newtype (List TypeMap a)                     } deriving (Functor, Foldable, Traversable)  instance TrieMap TypeMap Type where-  emptyTM = TM { tvar = emptyTM, tcon = emptyTM, trec = emptyTM }+  emptyTM = TM { tvar = emptyTM, tcon = emptyTM, trec = emptyTM, tnewtype = emptyTM }    nullTM ty = and [ nullTM (tvar ty)                   , nullTM (tcon ty)-                  , nullTM (trec ty) ]+                  , nullTM (trec ty)+                  , nullTM (tnewtype ty)+                  ]    lookupTM ty =     case ty of@@ -134,6 +137,7 @@       TCon c ts   -> lookupTM ts <=< lookupTM c . tcon       TRec fs     -> let (xs,ts) = unzip $ canonicalFields fs                      in lookupTM ts <=< lookupTM xs . trec+      TNewtype nt ts -> lookupTM ts <=< lookupTM nt . tnewtype    alterTM ty f m =     case ty of@@ -142,6 +146,7 @@       TCon c ts   -> m { tcon = alterTM c (updSub ts f) (tcon m) }       TRec fs     -> let (xs,ts) = unzip $ canonicalFields fs                      in m { trec = alterTM xs (updSub ts f) (trec m) }+      TNewtype nt ts -> m { tnewtype = alterTM nt (updSub ts f) (tnewtype m) }    toListTM m =     [ (TVar x,           v) | (x,v)   <- toListTM (tvar m) ] ++@@ -152,11 +157,16 @@     --  It's not clear if we should try to fix this.     [ (TRec (recordFromFields (zip fs ts)), v)           | (fs,m1) <- toListTM (trec m)-          , (ts,v)  <- toListTM m1 ]+          , (ts,v)  <- toListTM m1 ] ++ +    [ (TNewtype nt ts, v) | (nt,m1) <- toListTM (tnewtype m)+                          , (ts,v)  <- toListTM m1+    ]+   unionTM f m1 m2 = TM { tvar = unionTM f (tvar m1) (tvar m2)                        , tcon = unionTM (unionTM f) (tcon m1) (tcon m2)                        , trec = unionTM (unionTM f) (trec m1) (trec m2)+                       , tnewtype = unionTM (unionTM f) (tnewtype m1) (tnewtype m2)                        }    mapMaybeWithKeyTM f m =@@ -167,6 +177,8 @@                              (\ts a -> f (TRec (recordFromFields (zip fs ts))) a) l) (trec m)                                -- NB: this step loses 'displayOrder' information.                                --  It's not clear if we should try to fix this.+       , tnewtype = mapWithKeyTM (\nt l -> mapMaybeWithKeyTM+                                 (\ts a -> f (TNewtype nt ts) a) l) (tnewtype m)        }  
src/Cryptol/TypeCheck/TypeOf.hs view
@@ -30,6 +30,7 @@ fastTypeOf tyenv expr =   case expr of     -- Monomorphic fragment+    ELocated _ t  -> fastTypeOf tyenv t     EList es t    -> tSeq (tNum (length es)) t     ETuple es     -> tTuple (map (fastTypeOf tyenv) es)     ERec fields   -> tRec (fmap (fastTypeOf tyenv) fields)@@ -59,6 +60,8 @@ fastSchemaOf :: Map Name Schema -> Expr -> Schema fastSchemaOf tyenv expr =   case expr of+    ELocated _ e -> fastSchemaOf tyenv e+     -- Polymorphic fragment     EVar x         -> case Map.lookup x tyenv of                          Just ty -> ty@@ -113,10 +116,11 @@ plainSubst :: Subst -> Type -> Type plainSubst s ty =   case ty of-    TCon tc ts   -> TCon tc (map (plainSubst s) ts)-    TUser f ts t -> TUser f (map (plainSubst s) ts) (plainSubst s t)-    TRec fs      -> TRec (fmap (plainSubst s) fs)-    TVar x       -> apSubst s (TVar x)+    TCon tc ts     -> TCon tc (map (plainSubst s) ts)+    TUser f ts t   -> TUser f (map (plainSubst s) ts) (plainSubst s t)+    TRec fs        -> TRec (fmap (plainSubst s) fs)+    TNewtype nt ts -> TNewtype nt (map (plainSubst s) ts)+    TVar x         -> apSubst s (TVar x)  -- | Yields the return type of the selector on the given argument type. typeSelect :: Type -> Selector -> Type
src/Cryptol/TypeCheck/TypePat.hs view
@@ -7,7 +7,9 @@   , aCeilDiv, aCeilMod   , aLenFromThenTo -  , aLiteral, aLogic+  , aLiteral+  , aLiteralLessThan+  , aLogic    , aTVar   , aFreeTVar@@ -177,6 +179,9 @@  aLiteral :: Pat Prop (Type,Type) aLiteral = tp PLiteral ar2++aLiteralLessThan :: Pat Prop (Type,Type)+aLiteralLessThan = tp PLiteralLessThan ar2  aLogic :: Pat Prop Type aLogic = tp PLogic ar1
src/Cryptol/TypeCheck/Unify.hs view
@@ -74,6 +74,9 @@ mgu (TRec fs1) (TRec fs2)   | fieldSet fs1 == fieldSet fs2 = mguMany (recordElements fs1) (recordElements fs2) +mgu (TNewtype ntx xs) (TNewtype nty ys)+  | ntx == nty = mguMany xs ys+ mgu t1 t2   | not (k1 == k2)  = uniError $ UniKindMismatch k1 k2   | otherwise       = uniError $ UniTypeMismatch t1 t2
src/Cryptol/Utils/PP.hs view
@@ -27,6 +27,38 @@ import Prelude () import Prelude.Compat ++-- | How to pretty print things when evaluating+data PPOpts = PPOpts+  { useAscii     :: Bool+  , useBase      :: Int+  , useInfLength :: Int+  , useFPBase    :: Int+  , useFPFormat  :: PPFloatFormat+  }+ deriving Show++asciiMode :: PPOpts -> Integer -> Bool+asciiMode opts width = useAscii opts && (width == 7 || width == 8)++data PPFloatFormat =+    FloatFixed Int PPFloatExp -- ^ Use this many significant digis+  | FloatFrac Int             -- ^ Show this many digits after floating point+  | FloatFree PPFloatExp      -- ^ Use the correct number of digits+ deriving Show++data PPFloatExp = ForceExponent -- ^ Always show an exponent+                | AutoExponent  -- ^ Only show exponent when needed+ deriving Show+++defaultPPOpts :: PPOpts+defaultPPOpts = PPOpts { useAscii = False, useBase = 10, useInfLength = 5+                       , useFPBase = 16+                       , useFPFormat = FloatFree AutoExponent+                       }++ -- Name Displaying -------------------------------------------------------------  {- | How to display names, inspired by the GHC `Outputable` module.
src/GitRev.hs view
@@ -24,4 +24,3 @@  dirty :: Bool dirty = $(gitDirty)--- Last build Fri Sep 11 16:44:33 PDT 2020
utils/CryHtml.hs view
@@ -1,6 +1,7 @@ #!/usr/bin/env runhaskell  {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}  -- | -- Module      :  Main@@ -11,13 +12,14 @@ -- Portability :  portable  import Cryptol.Parser.Lexer+import Cryptol.Parser.Position import Cryptol.Utils.PP import qualified Data.Text.IO as Text-import Text.Blaze.Html (Html, AttributeValue, toValue, toHtml, (!))+import Text.Blaze.Html (Html, AttributeValue, toHtml, (!), toValue) import qualified Text.Blaze.Html as H import qualified Text.Blaze.Html5 as H import qualified Text.Blaze.Html5.Attributes as A-import Text.Blaze.Html.Renderer.Pretty (renderHtml)+import Text.Blaze.Html.Renderer.String (renderHtml)   main :: IO ()@@ -41,8 +43,9 @@   toBlaze :: Located Token -> Html+toBlaze (Located _ (tokenType -> EOF)) = mempty toBlaze tok = H.span ! (A.class_ $ cl $ tokenType $ thing tok)-                     ! (A.title $ toValue $ show $ pp $ srcRange tok)+                     ! (A.id $ toValue $ show $ pp $ from $ srcRange tok)   $ H.toHtml   $ tokenText   $ thing tok@@ -70,7 +73,7 @@  sty :: String sty = unlines-  [ "body { font-family: monospace }"+  [ "body { font-family: monospace; white-space: pre; }"   , ".number        { color: #cc00cc }"   , ".identifier    { }"   , ".selector      { color: #33033 }"