packages feed

stgi-1: test/Testsuite/Test/Machine/Evaluate/TestTemplates/Util.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes        #-}

module Test.Machine.Evaluate.TestTemplates.Util (
    hasValue,
    isLambdaForm,
    PrettyprinterDict(..),
) where


import           Data.Monoid
import           Data.Text                    (Text)
import qualified Data.Text                    as T
import           Text.PrettyPrint.ANSI.Leijen (Doc)

import Stg.Language
import Stg.Machine.Env
import Stg.Machine.Heap  as H
import Stg.Machine.Types
import Stg.Marshal
import Stg.Util



-- | Check whether a variable has a certain value in an STG state.
hasValue
    :: (Eq value, FromStg value)
    => Var
    -> value
    -> StgState
    -> Bool
var `hasValue` x = \state -> fromStg state var == Right x

-- | Build a state predicate that asserts that a certain 'Var' maps to
-- a 'LambdaForm' in the heap.
isLambdaForm :: Var -> LambdaForm -> StgState -> Bool
var `isLambdaForm` lambdaForm = \state -> case varLookup state var of
    VarLookupClosure (Closure lf _) -> lf == lambdaForm
    _otherwise                      -> False

-- | Used as the result of 'varLookup'.
data VarLookupResult =
    VarLookupError Text
    | VarLookupPrim Integer
    | VarLookupClosure Closure
    | VarLookupBlackhole
    deriving (Eq, Ord, Show)

-- | Look up the value of a 'Var' on the 'Heap' of a 'StgState'.
varLookup :: StgState -> Var -> VarLookupResult
varLookup state var =
    case globalVal (stgGlobals state) (AtomVar var) of
        Failure (NotInScope notInScope) -> VarLookupError
            (T.intercalate ", " (map (\(Var v) -> v) notInScope) <> " not in global scope")
        Success (Addr addr) -> case H.lookup addr (stgHeap state) of
            Just (HClosure closure)  -> VarLookupClosure closure
            Just (Blackhole _bhTick) -> VarLookupBlackhole
            Nothing                  -> VarLookupError "not found on heap"
        Success (PrimInt i) -> VarLookupPrim i

data PrettyprinterDict = PrettyprinterDict (forall a. Pretty a => a -> Text)
                                           (forall a. Pretty a => a -> Doc)