mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-12-17 21:11:35 +03:00
Use custom applicative functor to speed up interpreter on list comprehensions
This commit is contained in:
parent
e5e190a138
commit
c9a57766be
@ -28,11 +28,11 @@ import Cryptol.Utils.Panic (panic)
|
|||||||
import Cryptol.Utils.PP
|
import Cryptol.Utils.PP
|
||||||
import Cryptol.Prims.Eval
|
import Cryptol.Prims.Eval
|
||||||
|
|
||||||
import Control.Applicative (pure, ZipList(..))
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Data.Traversable (traverse)
|
import Data.Traversable (sequenceA)
|
||||||
|
|
||||||
#if __GLASGOW_HASKELL__ < 710
|
#if __GLASGOW_HASKELL__ < 710
|
||||||
|
import Control.Applicative (Applicative(..))
|
||||||
import Data.Monoid (Monoid(..),mconcat)
|
import Data.Monoid (Monoid(..),mconcat)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -168,31 +168,53 @@ evalSel env e sel = case sel of
|
|||||||
|
|
||||||
-- List Comprehension Environments ---------------------------------------------
|
-- List Comprehension Environments ---------------------------------------------
|
||||||
|
|
||||||
|
-- | A variation of the ZipList type from Control.Applicative, with a
|
||||||
|
-- separate constructor for pure values. This datatype is used to
|
||||||
|
-- represent the list of values that each variable takes on within a
|
||||||
|
-- list comprehension. The @Zip@ constructor is for bindings that take
|
||||||
|
-- different values at different positions in the list, while the
|
||||||
|
-- @Pure@ constructor is for bindings originating outside the list
|
||||||
|
-- comprehension, which have the same value for all list positions.
|
||||||
|
data ZList a = Pure a | Zip [a]
|
||||||
|
|
||||||
|
getZList :: ZList a -> [a]
|
||||||
|
getZList (Pure x) = repeat x
|
||||||
|
getZList (Zip xs) = xs
|
||||||
|
|
||||||
|
instance Functor ZList where
|
||||||
|
fmap f (Pure x) = Pure (f x)
|
||||||
|
fmap f (Zip xs) = Zip (map f xs)
|
||||||
|
|
||||||
|
instance Applicative ZList where
|
||||||
|
pure x = Pure x
|
||||||
|
Pure f <*> Pure x = Pure (f x)
|
||||||
|
Pure f <*> Zip xs = Zip (map f xs)
|
||||||
|
Zip fs <*> Pure x = Zip (map ($ x) fs)
|
||||||
|
Zip fs <*> Zip xs = Zip (zipWith ($) fs xs)
|
||||||
|
|
||||||
-- | Evaluation environments for list comprehensions: Each variable
|
-- | Evaluation environments for list comprehensions: Each variable
|
||||||
-- name is bound to a list of values, one for each element in the list
|
-- name is bound to a list of values, one for each element in the list
|
||||||
-- comprehension. The Left constructor is for "pure" bindings
|
-- comprehension.
|
||||||
-- originating outside the list comprehension, which have the same
|
|
||||||
-- value for all list positions.
|
|
||||||
data ListEnv = ListEnv
|
data ListEnv = ListEnv
|
||||||
{ leVars :: Map.Map QName (Either Value [Value])
|
{ leVars :: Map.Map QName (ZList Value)
|
||||||
, leTypes :: Map.Map TVar TValue
|
, leTypes :: Map.Map TVar TValue
|
||||||
}
|
}
|
||||||
|
|
||||||
instance Monoid ListEnv where
|
instance Monoid ListEnv where
|
||||||
mempty = ListEnv
|
mempty = ListEnv
|
||||||
{ leVars = Map.empty
|
{ leVars = Map.empty
|
||||||
, leTypes = Map.empty
|
, leTypes = Map.empty
|
||||||
}
|
}
|
||||||
|
|
||||||
mappend l r = ListEnv
|
mappend l r = ListEnv
|
||||||
{ leVars = Map.union (leVars l) (leVars r)
|
{ leVars = Map.union (leVars l) (leVars r)
|
||||||
, leTypes = Map.union (leTypes l) (leTypes r)
|
, leTypes = Map.union (leTypes l) (leTypes r)
|
||||||
}
|
}
|
||||||
|
|
||||||
toListEnv :: EvalEnv -> ListEnv
|
toListEnv :: EvalEnv -> ListEnv
|
||||||
toListEnv e =
|
toListEnv e =
|
||||||
ListEnv
|
ListEnv
|
||||||
{ leVars = fmap Left (envVars e)
|
{ leVars = fmap Pure (envVars e)
|
||||||
, leTypes = envTypes e
|
, leTypes = envTypes e
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,10 +225,10 @@ toListEnv e =
|
|||||||
zipListEnv :: ListEnv -> [EvalEnv]
|
zipListEnv :: ListEnv -> [EvalEnv]
|
||||||
zipListEnv (ListEnv vm tm) =
|
zipListEnv (ListEnv vm tm) =
|
||||||
[ EvalEnv { envVars = v, envTypes = tm }
|
[ EvalEnv { envVars = v, envTypes = tm }
|
||||||
| v <- getZipList (traverse (either pure ZipList) vm) ]
|
| v <- getZList (sequenceA vm) ]
|
||||||
|
|
||||||
bindVarList :: QName -> [Value] -> ListEnv -> ListEnv
|
bindVarList :: QName -> [Value] -> ListEnv -> ListEnv
|
||||||
bindVarList n vs lenv = lenv { leVars = Map.insert n (Right vs) (leVars lenv) }
|
bindVarList n vs lenv = lenv { leVars = Map.insert n (Zip vs) (leVars lenv) }
|
||||||
|
|
||||||
|
|
||||||
-- List Comprehensions ---------------------------------------------------------
|
-- List Comprehensions ---------------------------------------------------------
|
||||||
@ -242,8 +264,8 @@ evalMatch lenv m = case m of
|
|||||||
From n _ty expr -> bindVarList n (concat vss) lenv'
|
From n _ty expr -> bindVarList n (concat vss) lenv'
|
||||||
where
|
where
|
||||||
vss = [ fromSeq (evalExpr env expr) | env <- zipListEnv lenv ]
|
vss = [ fromSeq (evalExpr env expr) | env <- zipListEnv lenv ]
|
||||||
stutter (Left x) = Left x
|
stutter (Pure x) = Pure x
|
||||||
stutter (Right xs) = Right [ x | (x, vs) <- zip xs vss, _ <- vs ]
|
stutter (Zip xs) = Zip [ x | (x, vs) <- zip xs vss, _ <- vs ]
|
||||||
lenv' = lenv { leVars = fmap stutter (leVars lenv) }
|
lenv' = lenv { leVars = fmap stutter (leVars lenv) }
|
||||||
|
|
||||||
-- XXX we don't currently evaluate these as though they could be recursive, as
|
-- XXX we don't currently evaluate these as though they could be recursive, as
|
||||||
|
Loading…
Reference in New Issue
Block a user