mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-12-01 08:32:23 +03:00
Merge pull request #459 from GaloisInc/rwd/linear-unifier
Add a rule to the numeric solver for "linear unifiers"
This commit is contained in:
commit
cad6e1fe77
@ -14,7 +14,7 @@ import Cryptol.TypeCheck.TypePat
|
|||||||
import Cryptol.TypeCheck.Solver.Types
|
import Cryptol.TypeCheck.Solver.Types
|
||||||
import Cryptol.TypeCheck.Solver.InfNat
|
import Cryptol.TypeCheck.Solver.InfNat
|
||||||
import Cryptol.TypeCheck.Solver.Numeric.Interval
|
import Cryptol.TypeCheck.Solver.Numeric.Interval
|
||||||
import Cryptol.TypeCheck.SimpType
|
import Cryptol.TypeCheck.SimpType as Simp
|
||||||
|
|
||||||
{- Convention for comments:
|
{- Convention for comments:
|
||||||
|
|
||||||
@ -40,8 +40,8 @@ cryIsEqual ctxt t1 t2 =
|
|||||||
<|> tryEqMulConst t1 t2
|
<|> tryEqMulConst t1 t2
|
||||||
<|> tryEqAddInf ctxt t1 t2
|
<|> tryEqAddInf ctxt t1 t2
|
||||||
<|> tryAddConst (=#=) t1 t2
|
<|> tryAddConst (=#=) t1 t2
|
||||||
|
<|> tryLinearSolution t1 t2
|
||||||
|
<|> tryLinearSolution t2 t1
|
||||||
|
|
||||||
-- | Try to solve @t1 /= t2@
|
-- | Try to solve @t1 /= t2@
|
||||||
cryIsNotEqual :: Ctxt -> Type -> Type -> Solved
|
cryIsNotEqual :: Ctxt -> Type -> Type -> Solved
|
||||||
@ -331,3 +331,46 @@ tryAddConst rel l r =
|
|||||||
if k1 > k2
|
if k1 > k2
|
||||||
then return (SolvedIf [ tAdd (tNum (k1 - k2)) x2 `rel` y2 ])
|
then return (SolvedIf [ tAdd (tNum (k1 - k2)) x2 `rel` y2 ])
|
||||||
else return (SolvedIf [ x2 `rel` tAdd (tNum (k2 - k1)) y2 ])
|
else return (SolvedIf [ x2 `rel` tAdd (tNum (k2 - k1)) y2 ])
|
||||||
|
|
||||||
|
|
||||||
|
-- | Check for situations where a unification variable is involved in
|
||||||
|
-- a sum of terms not containing additional unification variables,
|
||||||
|
-- and replace it with a solution and an inequality.
|
||||||
|
-- @s1 = ?a + s2 ~~> (?a = s1 - s2, s1 >= s2)@
|
||||||
|
tryLinearSolution :: Type -> Type -> Match Solved
|
||||||
|
tryLinearSolution s1 t =
|
||||||
|
do (a,xs) <- matchLinearUnifier t
|
||||||
|
guard (noFreeVariables s1)
|
||||||
|
|
||||||
|
-- NB: matchLinearUnifier only matches if xs is nonempty
|
||||||
|
let s2 = foldr1 Simp.tAdd xs
|
||||||
|
return (SolvedIf [ TVar a =#= (Simp.tSub s1 s2), s1 >== s2 ])
|
||||||
|
|
||||||
|
|
||||||
|
-- | Match a sum of the form @(s1 + ... + ?a + ... sn)@ where
|
||||||
|
-- @s1@ through @sn@ do not contain any free variables.
|
||||||
|
--
|
||||||
|
-- Note: a successful match should only occur if @s1 ... sn@ is
|
||||||
|
-- not empty.
|
||||||
|
matchLinearUnifier :: Pat Type (TVar,[Type])
|
||||||
|
matchLinearUnifier = go []
|
||||||
|
where
|
||||||
|
go xs t =
|
||||||
|
-- Case where a free variable occurs at the end of a sequence of additions.
|
||||||
|
-- NB: match fails if @xs@ is empty
|
||||||
|
do v <- aFreeTVar t
|
||||||
|
guard (not . null $ xs)
|
||||||
|
return (v, xs)
|
||||||
|
<|>
|
||||||
|
-- Next symbol is an addition
|
||||||
|
do (x, y) <- anAdd t
|
||||||
|
|
||||||
|
-- Case where a free variable occurs in the middle of an expression
|
||||||
|
(do v <- aFreeTVar x
|
||||||
|
guard (noFreeVariables y)
|
||||||
|
return (v, reverse (y:xs))
|
||||||
|
|
||||||
|
<|>
|
||||||
|
-- Non-free-variable recursive case
|
||||||
|
do guard (noFreeVariables x)
|
||||||
|
go (x:xs) y)
|
||||||
|
@ -636,6 +636,8 @@ pError msg = TCon (TError KProp msg) []
|
|||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
noFreeVariables :: FVS t => t -> Bool
|
||||||
|
noFreeVariables = all (not . isFreeTV) . Set.toList . fvs
|
||||||
|
|
||||||
class FVS t where
|
class FVS t where
|
||||||
fvs :: t -> Set TVar
|
fvs :: t -> Set TVar
|
||||||
|
@ -7,6 +7,7 @@ module Cryptol.TypeCheck.TypePat
|
|||||||
, aLenFromThen, aLenFromThenTo
|
, aLenFromThen, aLenFromThenTo
|
||||||
|
|
||||||
, aTVar
|
, aTVar
|
||||||
|
, aFreeTVar
|
||||||
, aBit
|
, aBit
|
||||||
, aSeq
|
, aSeq
|
||||||
, aWord
|
, aWord
|
||||||
@ -112,6 +113,12 @@ aTVar = \a -> case tNoUser a of
|
|||||||
TVar x -> return x
|
TVar x -> return x
|
||||||
_ -> mzero
|
_ -> mzero
|
||||||
|
|
||||||
|
aFreeTVar :: Pat Type TVar
|
||||||
|
aFreeTVar t =
|
||||||
|
do v <- aTVar t
|
||||||
|
guard (isFreeTV v)
|
||||||
|
return v
|
||||||
|
|
||||||
aBit :: Pat Type ()
|
aBit :: Pat Type ()
|
||||||
aBit = tc TCBit ar0
|
aBit = tc TCBit ar0
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
Known tc failure. See issue #212.
|
|
@ -0,0 +1,3 @@
|
|||||||
|
Loading module Cryptol
|
||||||
|
Loading module Cryptol
|
||||||
|
Loading module Main
|
Loading…
Reference in New Issue
Block a user