Use appropriate markup for haddock code snippets.

Fixes #648.
This commit is contained in:
Brian Huffman 2019-10-21 15:24:01 -07:00
parent 0a68d4e3a1
commit d163e61c63
8 changed files with 94 additions and 94 deletions

View File

@ -105,7 +105,7 @@ infiniteSeqMap xs =
-- TODO: use an int-trie?
memoMap (IndexSeqMap $ \i -> genericIndex xs i)
-- | Create a finite list of length `n` of the values from [0..n-1] in
-- | 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 b w i -> [Eval (GenValue b w i)]
enumerateSeqMap n m = [ lookupSeqMap m i | i <- [0 .. (toInteger n)-1] ]
@ -124,7 +124,7 @@ updateSeqMap :: SeqMap b w i -> Integer -> Eval (GenValue b w i) -> SeqMap b w i
updateSeqMap (UpdateSeqMap m sm) i x = UpdateSeqMap (Map.insert i x m) sm
updateSeqMap (IndexSeqMap f) i x = UpdateSeqMap (Map.singleton i x) f
-- | Concatenate the first `n` values of the first sequence map onto the
-- | Concatenate the first @n@ values of the first sequence map onto the
-- beginning of the second sequence map.
concatSeqMap :: Integer -> SeqMap b w i -> SeqMap b w i -> SeqMap b w i
concatSeqMap n x y =
@ -133,16 +133,16 @@ concatSeqMap n x y =
then lookupSeqMap x i
else lookupSeqMap y (i-n)
-- | Given a number `n` and a sequence map, return two new sequence maps:
-- the first containing the values from `[0..n-1]` and the next containing
-- the values from `n` onward.
-- | Given a number @n@ and a sequence map, return two new sequence maps:
-- the first containing the values from @[0..n-1]@ and the next containing
-- the values from @n@ onward.
splitSeqMap :: Integer -> SeqMap b w i -> (SeqMap b w i, SeqMap b w i)
splitSeqMap n xs = (hd,tl)
where
hd = xs
tl = IndexSeqMap $ \i -> lookupSeqMap xs (i+n)
-- | Drop the first @n@ elements of the given @SeqMap@.
-- | Drop the first @n@ elements of the given 'SeqMap'.
dropSeqMap :: Integer -> SeqMap b w i -> SeqMap b w i
dropSeqMap 0 xs = xs
dropSeqMap n xs = IndexSeqMap $ \i -> lookupSeqMap xs (i+n)
@ -194,11 +194,11 @@ data WordValue b w i
= WordVal !w -- ^ Packed word representation for bit sequences.
| BitsVal !(Seq.Seq (Eval b)) -- ^ Sequence of thunks representing bits.
| LargeBitsVal !Integer !(SeqMap b w i ) -- ^ A large bitvector sequence, represented as a
-- @SeqMap@ of bits.
-- 'SeqMap' of bits.
deriving (Generic, NFData)
-- | An arbitrarily-chosen number of elements where we switch from a dense
-- sequence representation of bit-level words to @SeqMap@ representation.
-- sequence representation of bit-level words to 'SeqMap' representation.
largeBitSize :: Integer
largeBitSize = 1 `shiftL` 16
@ -256,7 +256,7 @@ indexWordValue (LargeBitsVal n xs) idx
| idx < n = fromBit =<< lookupSeqMap xs idx
| otherwise = invalidIndex idx
-- | Produce a new @WordValue@ from the one given by updating the @i@th bit with the
-- | Produce a new 'WordValue' from the one given by updating the @i@th bit with the
-- given bit value.
updateWordValue :: BitWord b w i => WordValue b w i -> Integer -> Eval b -> Eval (WordValue b w i)
updateWordValue (WordVal w) idx (Ready b)
@ -275,9 +275,9 @@ updateWordValue (LargeBitsVal n xs) idx b
-- | Generic value type, parameterized by bit and word types.
--
-- NOTE: we maintain an important invariant regarding sequence types.
-- `VSeq` must never be used for finite sequences of bits.
-- Always use the `VWord` constructor instead! Infinite sequences of bits
-- are handled by the `VStream` constructor, just as for other types.
-- 'VSeq' must never be used for finite sequences of bits.
-- Always use the 'VWord' constructor instead! Infinite sequences of bits
-- are handled by the 'VStream' constructor, just as for other types.
data GenValue b w i
= VRecord ![(Ident, Eval (GenValue b w i))] -- ^ @ { .. } @
| VTuple ![Eval (GenValue b w i)] -- ^ @ ( .. ) @
@ -433,7 +433,7 @@ class BitWord b w i | b -> w, w -> i, i -> b where
-- | Pretty-print an integer value
ppInteger :: PPOpts -> i -> Doc
-- | Attempt to render a word value as an ASCII character. Return `Nothing`
-- | Attempt to render a word value as an ASCII character. Return 'Nothing'
-- if the character value is unknown (e.g., for symbolic values).
wordAsChar :: w -> Maybe Char
@ -491,9 +491,9 @@ class BitWord b w i | b -> w, w -> i, i -> b where
-- The first integer argument is the number of bits in the
-- resulting word. The second integer argument is the
-- number of less-significant digits to discard. Stated another
-- way, the operation `extractWord n i w` is equivalent to
-- first shifting `w` right by `i` bits, and then truncating to
-- `n` bits.
-- way, the operation @extractWord n i w@ is equivalent to
-- first shifting @w@ right by @i@ bits, and then truncating to
-- @n@ bits.
extractWord :: Integer -- ^ Number of bits to take
-> Integer -- ^ starting bit
-> w
@ -641,11 +641,11 @@ lam = VFun
wlam :: BitWord b w i => (w -> Eval (GenValue b w i)) -> GenValue b w i
wlam f = VFun (\x -> x >>= fromVWord "wlam" >>= f)
-- | A type lambda that expects a @Type@.
-- | A type lambda that expects a 'Type'.
tlam :: (TValue -> GenValue b w i) -> GenValue b w i
tlam f = VPoly (return . f)
-- | A type lambda that expects a @Type@ of kind #.
-- | A type lambda that expects a 'Type' of kind #.
nlam :: (Nat' -> GenValue b w i) -> GenValue b w i
nlam f = VNumPoly (return . f)
@ -736,7 +736,7 @@ vWordLen val = case val of
-- | If the given list of values are all fully-evaluated thunks
-- containing bits, return a packed word built from the same bits.
-- However, if any value is not a fully-evaluated bit, return `Nothing`.
-- However, if any value is not a fully-evaluated bit, return 'Nothing'.
tryFromBits :: BitWord b w i => [Eval (GenValue b w i)] -> Maybe w
tryFromBits = go id
where

View File

@ -30,8 +30,8 @@ type Gen g b w i = Integer -> g -> (GenValue b w i, g)
{- | Apply a testable value to some randomly-generated arguments.
Returns `Nothing` if the function returned `True`, or
`Just counterexample` if it returned `False`.
Returns @Nothing@ if the function returned @True@, or
@Just counterexample@ if it returned @False@.
Please note that this function assumes that the generators match
the supplied value, otherwise we'll panic.
@ -87,7 +87,7 @@ returnTests g evo gens fun num = go gens g 0
return ((inputs, output) : more)
{- | Given a (function) type, compute generators for the function's
arguments. This is like @testableType@, but allows the result to be
arguments. This is like 'testableType', but allows the result to be
any finite type instead of just @Bit@. -}
dumpableType :: forall g. RandomGen g => Type -> Maybe [Gen g Bool BV Integer]
dumpableType ty =

View File

@ -10,62 +10,62 @@
-- slow down in some cases. What's the problem? Consider the following (common)
-- patterns:
--
-- fibs = [0,1] # [ x + y | x <- fibs, y <- drop`{1} fibs ]
-- > fibs = [0,1] # [ x + y | x <- fibs, y <- drop`{1} fibs ]
--
-- The type of `fibs` is:
-- The type of @fibs@ is:
--
-- {a} (a >= 1, fin a) => [inf][a]
-- > {a} (a >= 1, fin a) => [inf][a]
--
-- Here `a` is the number of bits to be used in the values computed by `fibs`.
-- When we evaluate `fibs`, `a` becomes a parameter to `fibs`, which works
-- except that now `fibs` is a function, and we don't get any of the memoization
-- Here @a@ is the number of bits to be used in the values computed by @fibs@.
-- When we evaluate @fibs@, @a@ becomes a parameter to @fibs@, which works
-- except that now @fibs@ is a function, and we don't get any of the memoization
-- we might expect! What looked like an efficient implementation has all
-- of a sudden become exponential!
--
-- Note that this is only a problem for polymorphic values: if `fibs` was
-- Note that this is only a problem for polymorphic values: if @fibs@ was
-- already a function, it would not be that surprising that it does not
-- get cached.
--
-- So, to avoid this, we try to spot recursive polymorphic values,
-- where the recursive occurrences have the exact same type parameters
-- as the definition. For example, this is the case in `fibs`: each
-- recursive call to `fibs` is instantiated with exactly the same
-- type parameter (i.e., `a`). The rewrite we do is as follows:
-- as the definition. For example, this is the case in @fibs@: each
-- recursive call to @fibs@ is instantiated with exactly the same
-- type parameter (i.e., @a@). The rewrite we do is as follows:
--
-- fibs : {a} (a >= 1, fin a) => [inf][a]
-- fibs = \{a} (a >= 1, fin a) -> fibs'
-- where fibs' : [inf][a]
-- fibs' = [0,1] # [ x + y | x <- fibs', y <- drop`{1} fibs' ]
-- > fibs : {a} (a >= 1, fin a) => [inf][a]
-- > fibs = \{a} (a >= 1, fin a) -> fibs'
-- > where fibs' : [inf][a]
-- > fibs' = [0,1] # [ x + y | x <- fibs', y <- drop`{1} fibs' ]
--
-- After the rewrite, the recursion is monomorphic (i.e., we are always using
-- the same type). As a result, `fibs'` is an ordinary recursive value,
-- the same type). As a result, @fibs'@ is an ordinary recursive value,
-- where we get the benefit of caching.
--
-- The rewrite is a bit more complex, when there are multiple mutually
-- recursive functions. Here is an example:
--
-- zig : {a} (a >= 2, fin a) => [inf][a]
-- zig = [1] # zag
--
-- zag : {a} (a >= 2, fin a) => [inf][a]
-- zag = [2] # zig
-- > zig : {a} (a >= 2, fin a) => [inf][a]
-- > zig = [1] # zag
-- >
-- > zag : {a} (a >= 2, fin a) => [inf][a]
-- > zag = [2] # zig
--
-- This gets rewritten to:
--
-- newName : {a} (a >= 2, fin a) => ([inf][a], [inf][a])
-- newName = \{a} (a >= 2, fin a) -> (zig', zag')
-- where
-- zig' : [inf][a]
-- zig' = [1] # zag'
--
-- zag' : [inf][a]
-- zag' = [2] # zig'
--
-- zig : {a} (a >= 2, fin a) => [inf][a]
-- zig = \{a} (a >= 2, fin a) -> (newName a <> <> ).1
--
-- zag : {a} (a >= 2, fin a) => [inf][a]
-- zag = \{a} (a >= 2, fin a) -> (newName a <> <> ).2
-- > newName : {a} (a >= 2, fin a) => ([inf][a], [inf][a])
-- > newName = \{a} (a >= 2, fin a) -> (zig', zag')
-- > where
-- > zig' : [inf][a]
-- > zig' = [1] # zag'
-- >
-- > zag' : [inf][a]
-- > zag' = [2] # zig'
-- >
-- > zig : {a} (a >= 2, fin a) => [inf][a]
-- > zig = \{a} (a >= 2, fin a) -> (newName a <> <> ).1
-- >
-- > zag : {a} (a >= 2, fin a) => [inf][a]
-- > zag = \{a} (a >= 2, fin a) -> (newName a <> <> ).2
--
-- NOTE: We are assuming that no capture would occur with binders.
-- For values, this is because we replaces things with freshly chosen variables.
@ -92,8 +92,8 @@ import MonadLib hiding (mapM)
import Prelude ()
import Prelude.Compat
{- (f,t,n) |--> x means that when we spot instantiations of `f` with `ts` and
`n` proof argument, we should replace them with `Var x` -}
{- (f,t,n) |--> x means that when we spot instantiations of @f@ with @ts@ and
@n@ proof argument, we should replace them with @Var x@ -}
newtype RewMap' a = RM (Map Name (TypesMap (Map Int a)))
type RewMap = RewMap' Name

View File

@ -28,8 +28,8 @@ import Prelude.Compat
-- Specializer Monad -----------------------------------------------------------
-- | A Name should have an entry in the SpecCache iff it is
-- specializable. Each Name starts out with an empty TypesMap.
-- | A 'Name' should have an entry in the 'SpecCache' iff it is
-- specializable. Each 'Name' starts out with an empty 'TypesMap'.
type SpecCache = Map Name (Decl, TypesMap (Name, Maybe Decl))
-- | The specializer monad.
@ -58,7 +58,7 @@ modify f = get >>= (set . f)
-- Specializer -----------------------------------------------------------------
-- | Add a `where` clause to the given expression containing
-- | Add a @where@ clause to the given expression containing
-- type-specialized versions of all functions called (transitively) by
-- the body of the expression.
specialize :: Expr -> M.ModuleCmd Expr
@ -88,13 +88,13 @@ specializeExpr expr =
e' <- specializeExpr e
setSpecCache cache
return (ETAbs t e')
-- We need to make sure that after processing `e`, no specialized
-- decls mentioning type variable `t` escape outside the
-- `ETAbs`. To avoid this, we reset to an empty SpecCache while we
-- run `specializeExpr e`, and restore it afterward: this
-- We need to make sure that after processing @e@, no specialized
-- decls mentioning type variable @t@ escape outside the
-- 'ETAbs'. To avoid this, we reset to an empty 'SpecCache' while we
-- run @'specializeExpr' e@, and restore it afterward: this
-- effectively prevents the specializer from registering any type
-- instantiations involving `t` for any decls bound outside the
-- scope of `t`.
-- instantiations involving @t@ for any decls bound outside the
-- scope of @t@.
ETApp {} -> specializeConst expr
EApp e1 e2 -> EApp <$> specializeExpr e1 <*> specializeExpr e2
EAbs qn t e -> EAbs qn t <$> specializeExpr e
@ -144,9 +144,9 @@ withDeclGroups dgs action = do
modifySpecCache (Map.union savedCache . flip Map.difference newCache)
return (result, dgs', nameTable)
-- | Compute the specialization of `EWhere e dgs`. A decl within `dgs`
-- | Compute the specialization of @'EWhere' e dgs@. A decl within @dgs@
-- is replicated once for each monomorphic type instance at which it
-- is used; decls not mentioned in `e` (even monomorphic ones) are
-- is used; decls not mentioned in @e@ (even monomorphic ones) are
-- simply dropped.
specializeEWhere :: Expr -> [DeclGroup] -> SpecM Expr
specializeEWhere e dgs = do
@ -224,7 +224,7 @@ destETAbs = go []
-- Any top-level declarations in the current module can be found in the
-- ModuleEnv's LoadedModules, and so we can count of freshName to avoid
-- collisions with them. Any generated name for a
-- specialized function will be qualified with the current @ModName@, so genned
-- specialized function will be qualified with the current 'ModName', so genned
-- names will not collide with local decls either.
-- freshName :: Name -> [Type] -> SpecM Name
-- freshName n [] = return n
@ -322,7 +322,7 @@ instantiateSchema ts n (Forall params props ty)
| otherwise = return $ Forall [] [] (apSubst sub ty)
where sub = listParamSubst (zip params ts)
-- | Reduce `length ts` outermost type abstractions and `n` proof abstractions.
-- | Reduce @length ts@ outermost type abstractions and @n@ proof abstractions.
instantiateExpr :: [Type] -> Int -> Expr -> SpecM Expr
instantiateExpr [] 0 e = return e
instantiateExpr [] n (EProofAbs _ e) = instantiateExpr [] (n - 1) e

View File

@ -124,13 +124,13 @@ data Expr = EList [Expr] Type -- ^ List value (with type of elements)
{- | 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,
which should be of kind `KProp`.
record the assumption. The assumption is the 'Type' term,
which should be of kind 'KProp'.
-}
| EProofAbs {- x -} Prop Expr
{- | If `e : p => t`, then `EProofApp e : t`,
as long as we can prove `p`.
{- | If @e : p => t@, then @EProofApp e : t@,
as long as we can prove @p@.
We don't record the actual proofs, as they are not
used for anything. It may be nice to keep them around
@ -181,7 +181,7 @@ data DeclDef = DPrim
ePrim :: PrimMap -> Ident -> Expr
ePrim pm n = EVar (lookupPrimDecl n pm)
-- | Make an expression that is `error` pre-applied to a type and a message.
-- | Make an expression that is @error@ pre-applied to a type and a message.
eError :: PrimMap -> Type -> String -> Expr
eError prims t str =
EApp (ETApp (ETApp (ePrim prims (packIdent "error")) t)

View File

@ -192,7 +192,7 @@ data RO = RO
{- NOTE: We assume no shadowing between these two, so it does not matter
where we look first. Similarly, we assume no shadowing with
the existential type variable (in RW). See `checkTShadowing`. -}
the existential type variable (in RW). See 'checkTShadowing'. -}
, iTVars :: [TParam] -- ^ Type variable that are in scope
, iTSyns :: Map Name (DefLoc, TySyn) -- ^ Type synonyms that are in scope
@ -218,7 +218,7 @@ data RO = RO
, iSolvedHasLazy :: Map Int HasGoalSln
-- ^ NOTE: This field is lazy in an important way! It is the
-- final version of `iSolvedHas` in `RW`, and the two are tied
-- final version of 'iSolvedHas' in 'RW', and the two are tied
-- together through recursion. The field is here so that we can
-- look thing up before they are defined, which is OK because we
-- don't need to know the results until everything is done.
@ -263,8 +263,8 @@ data RW = RW
-- Constraints that need solving
, iCts :: !Goals -- ^ Ordinary constraints
, iHasCts :: ![HasGoal]
{- ^ Tuple/record projection constraints. The `Int` is the "name"
of the constraint, used so that we can name it solution properly. -}
{- ^ Tuple/record projection constraints. The 'Int' is the "name"
of the constraint, used so that we can name its solution properly. -}
, iSupply :: !Supply
}
@ -421,13 +421,13 @@ newHasGoal l ty f =
addHasGoal :: HasGoal -> InferM ()
addHasGoal g = IM $ sets_ $ \s -> s { iHasCts = g : iHasCts s }
-- | Get the `Has` constraints. Each of this should either be solved,
-- or added back using `addHasGoal`.
-- | Get the @Has@ constraints. Each of this should either be solved,
-- or added back using 'addHasGoal'.
getHasGoals :: InferM [HasGoal]
getHasGoals = do gs <- IM $ sets $ \s -> (iHasCts s, s { iHasCts = [] })
applySubst gs
-- | Specify the solution (`Expr -> Expr`) for the given constraint (`Int`).
-- | Specify the solution (@Expr -> Expr@) for the given constraint ('Int').
solveHasGoal :: Int -> HasGoalSln -> InferM ()
solveHasGoal n e =
IM $ sets_ $ \s -> s { iSolvedHas = Map.insert n e (iSolvedHas s) }
@ -535,7 +535,7 @@ getSubst :: InferM Subst
getSubst = IM $ fmap iSubst get
-- | Add to the accumulated substitution, checking that the datatype
-- invariant for `Subst` is maintained.
-- invariant for 'Subst' is maintained.
extendSubst :: Subst -> InferM ()
extendSubst su =
do mapM_ check (substToList su)

View File

@ -15,7 +15,7 @@ import Data.Maybe(listToMaybe)
-- | All ways to split a type in the form: `a + t1`, where `a` is a variable.
-- | All ways to split a type in the form: @a + t1@, where @a@ is a variable.
splitVarSummands :: Type -> [(TVar,Type)]
splitVarSummands ty0 = [ (x,t1) | (x,t1) <- go ty0, tNum (0::Int) /= t1 ]
where
@ -32,12 +32,12 @@ splitVarSummands ty0 = [ (x,t1) | (x,t1) <- go ty0, tNum (0::Int) /= t1 ]
TCon _ _ -> [] -- XXX: we could do some distributivity etc
-- | Check if we can express a type in the form: `a + t1`.
-- | Check if we can express a type in the form: @a + t1@.
splitVarSummand :: TVar -> Type -> Maybe Type
splitVarSummand a ty = listToMaybe [ t | (x,t) <- splitVarSummands ty, x == a ]
{- | Check if we can express a type in the form: `k + t1`,
where `k` is a constant > 0.
{- | Check if we can express a type in the form: @k + t1@,
where @k@ is a constant > 0.
This assumes that the type has been simplified already,
so that constants are floated to the left. -}
splitConstSummand :: Type -> Maybe (Integer, Type)
@ -54,8 +54,8 @@ splitConstSummand ty =
TCon (TC (TCNum k)) [] -> guard (k > 0) >> return (k, tNum (0::Int))
TCon {} -> Nothing
{- | Check if we can express a type in the form: `k * t1`,
where `k` is a constant > 1
{- | Check if we can express a type in the form: @k * t1@,
where @k@ is a constant > 1.
This assumes that the type has been simplified already,
so that constants are floated to the left. -}
splitConstFactor :: Type -> Maybe (Integer, Type)

View File

@ -99,8 +99,8 @@ data Type = TCon !TCon ![Type]
{- ^ This is just a type annotation, for a type that
was written as a type synonym. It is useful so that we
can use it to report nicer errors.
Example: `TUser T ts t` is really just the type `t` that
was written as `T ts` by the user. -}
Example: @TUser T ts t@ is really just the type @t@ that
was written as @T ts@ by the user. -}
| TRec ![(Ident,Type)]
-- ^ Record type
@ -157,7 +157,7 @@ tvSourceName tvs =
DefinitionOf x -> Just x
_ -> Nothing
-- | The type is supposed to be of kind `KProp`
-- | The type is supposed to be of kind 'KProp'.
type Prop = Type
@ -597,7 +597,7 @@ pLiteral x y = TCon (PC PLiteral) [x, y]
(>==) :: Type -> Type -> Prop
x >== y = TCon (PC PGeq) [x,y]
-- | A `Has` constraint, used for tuple and record selection.
-- | A @Has@ constraint, used for tuple and record selection.
pHas :: Selector -> Type -> Type -> Prop
pHas l ty fi = TCon (PC (PHas l)) [ty,fi]