The SSTG package

[Tags:bsd3, library, program, test]

Prototype of STG-based Symbolic Execution for Haskell.

[Skip to Readme]


Dependencies base (>=4.7 && <5), containers (==0.5.*), ghc, ghc-paths, SSTG [details]
License BSD3
Copyright 2017 Anton Xue
Author Anton Xue
Category Web
Home page
Source repository head: git clone
Uploaded Thu Aug 17 05:13:05 UTC 2017 by AntonXue
Distributions NixOS:
Downloads 493 total (493 in the last 30 days)
1 []
Status Docs available [build log]
Last success reported on 2017-08-17 [all 1 reports]
Hackage Matrix CI




Maintainer's Corner

For package maintainers and hackage trustees

Readme for SSTG

Readme for SSTG-


Haskell Symbolic Execution with STG Semantics

Based on the paper: Making a Fast Curry: Push/Enter vs. Eval/Apply for Higher-order Languages

Hackage Page:


  • ghc >= 8.0.1

Installation with Cabal

cabal install SSTG

As an API

SSTG is designed for use as an API to perform extraction and symbolic execution of models extracted from Haskell source, curated by hand, or derived from other sources.

import SSTG

Program Model Extraction

SSTG represents GHC StgSyn as a near one-to-one translation of an internal language called SSTG Lang.

This can be extracted from Haskell source by performing a call to the function:

mkTargetBindings :: FilePath -> FilePath -> IO [Binding]
mkTargetBinding proj src = ...

Here proj denotes the project directory, while src respresents the source file. This enables compilation of multiple Haskell files simultaneously, as GHC requires reference paths to a common project directory for compilation accuracy.

In a given file structure as follows:

  +-- project/
        +-- folder-one/
              +-- source.hs

The corresponding proj and src would be equivalent to:

proj = path/to/stuff
src  = path/to/stuff/folder-one/source.hs

The extracted [Binding], like almost everything in SSTG, is endowed with Show, Equal, Read. However, it is advised to use the pretty-print functions defined in SSTG.Utils.Printing. For instance:

pprBindingStr :: Binding -> String


Defunctionalization Wikipedia article

Symbolic Execution

Symbolic execution is done by performin a series of graph reductions on a State until we reach some value form, or our step_count tick runs out, creating a form of bounded execution exploration.

To load a State, two functions can be used:

data LoadResult = LoadOkay State | LoadGuess State [Binding] | LoadError String

newtype Program = Program [Binding]

loadState :: Program -> LoadResult

loadStateEntry :: String -> Program -> LoadResult

Next we have to fill out the flags for execution:

data StepType = BFS | BFSLogged | DFS | DFSLogged

data RunFlags = RunFlags { step_count :: Int
                         , step_type  :: StepType
                         , dump_dir   :: Maybe FilePath }

Here step_count is the number of steps we may take, the step_type is currently only implemented for BFS and BFSLogged, the latter of which keeps track of every step taken, while BFS only returns the very last state. Note that BFSLogged is currently unoptimized because it is easy to implement that way :)

Finally, to perform execution, the execute function is used:

execute :: RunFlags -> State -> [([LiveState], [DeadState])]

This yields a list of execution snapshots. The list is a singleton list if BFS or DFS is used, while multiple snapshots if the BFSLogged or DFSLogged is done. These can be then printed by using pprLivesDeadsStr:

pprLivesDeadsStr :: ([LiveState], [DeadState]) -> String

Constraint Solving

To come.


  • Defunctionalization pre-processing
  • SMT integration


  • Uninterpreted function evaluations are abstracted as symbolic computations. This includes all functions defined in Prelude and those not defined in the scope of the target programs.
  • There might be bugs, who knows? :)