mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-12-15 02:01:39 +03:00
Handle the case where evaluation of something crashes. Also add a new error for prims.
This commit is contained in:
parent
6190fcd752
commit
ed8fb2ae46
@ -32,6 +32,7 @@ module Cryptol.Eval.Monad
|
|||||||
, wordTooWide
|
, wordTooWide
|
||||||
, cryUserError
|
, cryUserError
|
||||||
, cryLoopError
|
, cryLoopError
|
||||||
|
, cryNoPrimError
|
||||||
, invalidIndex
|
, invalidIndex
|
||||||
) where
|
) where
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ import qualified Control.Exception as X
|
|||||||
import Cryptol.Utils.Panic
|
import Cryptol.Utils.Panic
|
||||||
import Cryptol.Utils.PP
|
import Cryptol.Utils.PP
|
||||||
import Cryptol.Utils.Logger(Logger)
|
import Cryptol.Utils.Logger(Logger)
|
||||||
import Cryptol.TypeCheck.AST(Type)
|
import Cryptol.TypeCheck.AST(Type,Name)
|
||||||
|
|
||||||
-- | A computation that returns an already-evaluated value.
|
-- | A computation that returns an already-evaluated value.
|
||||||
ready :: a -> Eval a
|
ready :: a -> Eval a
|
||||||
@ -75,7 +76,9 @@ data Eval a
|
|||||||
data ThunkState a
|
data ThunkState a
|
||||||
= Unforced -- ^ This thunk has not yet been forced
|
= Unforced -- ^ This thunk has not yet been forced
|
||||||
| BlackHole -- ^ This thunk is currently being evaluated
|
| BlackHole -- ^ This thunk is currently being evaluated
|
||||||
| Forced !a -- ^ This thunk has previously been forced, and has the given value
|
| Forced !(Either EvalError a)
|
||||||
|
-- ^ This thunk has previously been forced,
|
||||||
|
-- and has the given value, or evaluation resulted in an error.
|
||||||
|
|
||||||
|
|
||||||
-- | Access the evaluation options.
|
-- | Access the evaluation options.
|
||||||
@ -126,14 +129,19 @@ unDelay :: Eval a -> IORef (ThunkState a) -> IO a -> Eval a
|
|||||||
unDelay retry r x = do
|
unDelay retry r x = do
|
||||||
rval <- io $ readIORef r
|
rval <- io $ readIORef r
|
||||||
case rval of
|
case rval of
|
||||||
Forced val -> return val
|
Forced val -> io (toVal val)
|
||||||
BlackHole ->
|
BlackHole ->
|
||||||
retry
|
retry
|
||||||
Unforced -> io $ do
|
Unforced -> io $ do
|
||||||
writeIORef r BlackHole
|
writeIORef r BlackHole
|
||||||
val <- x
|
val <- X.try x
|
||||||
writeIORef r (Forced val)
|
writeIORef r (Forced val)
|
||||||
return val
|
toVal val
|
||||||
|
|
||||||
|
where
|
||||||
|
toVal mbV = case mbV of
|
||||||
|
Right a -> pure a
|
||||||
|
Left e -> X.throwIO e
|
||||||
|
|
||||||
-- | Execute the given evaluation action.
|
-- | Execute the given evaluation action.
|
||||||
runEval :: EvalOpts -> Eval a -> IO a
|
runEval :: EvalOpts -> Eval a -> IO a
|
||||||
@ -196,6 +204,7 @@ data EvalError
|
|||||||
| WordTooWide Integer -- ^ Bitvector too large
|
| WordTooWide Integer -- ^ Bitvector too large
|
||||||
| UserError String -- ^ Call to the Cryptol @error@ primitive
|
| UserError String -- ^ Call to the Cryptol @error@ primitive
|
||||||
| LoopError String -- ^ Detectable nontermination
|
| LoopError String -- ^ Detectable nontermination
|
||||||
|
| NoPrim Name -- ^ Primitive with no implementation
|
||||||
deriving (Typeable,Show)
|
deriving (Typeable,Show)
|
||||||
|
|
||||||
instance PP EvalError where
|
instance PP EvalError where
|
||||||
@ -209,6 +218,7 @@ instance PP EvalError where
|
|||||||
text "word too wide for memory:" <+> integer w <+> text "bits"
|
text "word too wide for memory:" <+> integer w <+> text "bits"
|
||||||
UserError x -> text "Run-time error:" <+> text x
|
UserError x -> text "Run-time error:" <+> text x
|
||||||
LoopError x -> text "<<loop>>" <+> text x
|
LoopError x -> text "<<loop>>" <+> text x
|
||||||
|
NoPrim x -> text "unimplemented primitive:" <+> pp x
|
||||||
|
|
||||||
instance X.Exception EvalError
|
instance X.Exception EvalError
|
||||||
|
|
||||||
@ -238,6 +248,9 @@ wordTooWide w = X.throw (WordTooWide w)
|
|||||||
cryUserError :: String -> Eval a
|
cryUserError :: String -> Eval a
|
||||||
cryUserError msg = io (X.throwIO (UserError msg))
|
cryUserError msg = io (X.throwIO (UserError msg))
|
||||||
|
|
||||||
|
cryNoPrimError :: Name -> Eval a
|
||||||
|
cryNoPrimError x = io (X.throwIO (NoPrim x))
|
||||||
|
|
||||||
-- | For cases where we can detect tight loops.
|
-- | For cases where we can detect tight loops.
|
||||||
cryLoopError :: String -> Eval a
|
cryLoopError :: String -> Eval a
|
||||||
cryLoopError msg = io (X.throwIO (LoopError msg))
|
cryLoopError msg = io (X.throwIO (LoopError msg))
|
||||||
|
Loading…
Reference in New Issue
Block a user