packages feed

crucible-0.7: src/Lang/Crucible/Backend/Simple.hs

------------------------------------------------------------------------
-- |
-- Module      : Lang.Crucible.Backend.Simple
-- Description : The "simple" solver backend
-- Copyright   : (c) Galois, Inc 2015-2016
-- License     : BSD3
-- Maintainer  : Rob Dockins <rdockins@galois.com>
-- Stability   : provisional
--
-- An "offline" backend for communicating with solvers.  This backend
-- does not maintain a persistent connection to a solver, and does
-- not perform satisfiability checks at symbolic branch points.
------------------------------------------------------------------------

{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Lang.Crucible.Backend.Simple
  ( -- * SimpleBackend
    SimpleBackend
  , newSimpleBackend
    -- * Re-exports
  , B.FloatMode
  , B.FloatModeRepr(..)
  , B.FloatIEEE
  , B.FloatUninterpreted
  , B.FloatReal
  , B.Flags
  ) where

import           Control.Lens ( (^.) )
import           Control.Monad (void)

import           What4.Config
import           What4.Interface
import qualified What4.Expr.Builder as B

import qualified Lang.Crucible.Backend.AssumptionStack as AS
import           Lang.Crucible.Backend
import           Lang.Crucible.Simulator.SimError

------------------------------------------------------------------------
-- SimpleBackendState

-- | This represents the state of the backend along a given execution.
-- It contains the current assertion stack.

type AS t =
     AssumptionStack (CrucibleAssumptions (B.Expr t))
                     (LabeledPred (B.BoolExpr t) SimError)

data SimpleBackend t st fs =
  SimpleBackend
  { sbAssumptionStack :: AS t
  , sbExprBuilder :: B.ExprBuilder t st fs
  }

newSimpleBackend ::
  B.ExprBuilder t st fs ->
  IO (SimpleBackend t st fs)
newSimpleBackend sym =
  do as <- AS.initAssumptionStack (sym ^. B.exprCounter)
     tryExtendConfig backendOptions (getConfiguration sym)
     return SimpleBackend
            { sbAssumptionStack = as
            , sbExprBuilder = sym
            }

instance HasSymInterface (B.ExprBuilder t st fs) (SimpleBackend t st fs) where
  backendGetSym = sbExprBuilder  

instance IsSymInterface (B.ExprBuilder t st fs) =>
  IsSymBackend (B.ExprBuilder t st fs) (SimpleBackend t st fs) where

  addDurableProofObligation bak a =
     AS.addProofObligation a (sbAssumptionStack bak)

  addAssumption bak a =
    case impossibleAssumption a of
      Just rsn -> abortExecBecause rsn
      Nothing  -> AS.appendAssumptions (singleAssumption a) (sbAssumptionStack bak)

  addAssumptions bak ps = do
    AS.appendAssumptions ps (sbAssumptionStack bak)

  collectAssumptions bak =
    AS.collectAssumptions (sbAssumptionStack bak)

  getPathCondition bak = do
    let sym = backendGetSym bak
    ps <- AS.collectAssumptions (sbAssumptionStack bak)
    assumptionsPred sym ps

  getProofObligations bak = do
    AS.getProofObligations (sbAssumptionStack bak)

  clearProofObligations bak = do
    AS.clearProofObligations (sbAssumptionStack bak)

  pushAssumptionFrame bak = do
    AS.pushFrame (sbAssumptionStack bak)

  popAssumptionFrame bak ident = do
    AS.popFrame ident (sbAssumptionStack bak)

  popAssumptionFrameAndObligations bak ident = do
    AS.popFrameAndGoals ident (sbAssumptionStack bak)

  popUntilAssumptionFrame bak ident = do
    void $ AS.popFramesUntil ident (sbAssumptionStack bak)

  saveAssumptionState bak = do
    AS.saveAssumptionStack (sbAssumptionStack bak)

  restoreAssumptionState bak newstk = do
    AS.restoreAssumptionStack newstk (sbAssumptionStack bak)