packages feed

copilot-2.0: Tests/Test.hs

--------------------------------------------------------------------------------
-- Copyright © 2011 National Institute of Aerospace / Galois, Inc.
--------------------------------------------------------------------------------

-- | A very small test suite to check for basic functionality.

{-# LANGUAGE RebindableSyntax #-}

module Main where

import qualified Prelude as P
import Language.Copilot hiding (even, odd)
import Copilot.Compile.C99

import System.Directory (removeFile)
--------------------------------------------------------------------------------

--
-- Some utility functions:
--

flipflop :: Stream Bool -> Stream Bool
flipflop x = y
  where
    y = [False] ++ if x then not y else y

nats :: Stream Word64
nats = [0] ++ nats + 1

even :: (P.Integral a, Typed a) => Stream a -> Stream Bool
even x = x `mod` 2 == 0

odd :: (P.Integral a, Typed a) => Stream a -> Stream Bool
odd = not . even

counter :: (Num a, Typed a) => Stream Bool -> Stream a
counter reset = y
  where
    zy = [0] ++ y
    y  = if reset then 0 else zy + 1

booleans :: Stream Bool
booleans = [True, True, False] ++ booleans

fib :: Stream Word64
fib = [1, 1] ++ fib + drop 1 fib

bitWise :: Stream Word8
bitWise = ( let a = [ 1, 1, 0 ] ++ a in a )
          .^.
          ( let b = [ 0, 1, 1 ] ++ b in b )

sumExterns :: Stream Word64
sumExterns =
  let
    ex1 = extern "e1"
    ex2 = extern "e2"
  in
    ex1 + ex2

--------------------------------------------------------------------------------

--
-- An example of a complete copilot specification.


-- A specification:
spec :: Spec 
spec =
  do
    -- A trigger with four arguments:
    trigger "e" booleans
      [ arg fib, arg nats, arg sumExterns, arg bitWise ]

    -- A trigger with two arguments:
    trigger "f" booleans
      [ arg fib, arg sumExterns ]

    -- A trigger with a single argument:
    trigger "g" (flipflop booleans)
      [ arg (sumExterns + counter false + 25) ]

    -- A trigger with a single argument (should never fire):
    trigger "h" (extern "e3" /= fib)
      [ arg (0 :: Stream Int8) ]

    observer "i" (odd nats)

--- Some infinite lists for simulating external variables:
e1, e2, e3 :: [Word64]
e1 = [0..]
e2 = 5 : 4 : e2
e3 = [1, 1] P.++ zipWith (+) e3 (P.drop 1 e3)

main :: IO ()
main = do
  putStrLn "PrettyPrinter:"
  putStrLn ""
  prettyPrint spec
  putStrLn ""
  putStrLn ""
  putStrLn "Interpreter:"
  putStrLn ""
  interpret 10 [var "e1" e1, var "e2" e2, var "e3" e3] spec
  putStrLn ""
  putStrLn ""
  putStrLn "Atom compilation:"
  reify spec >>= compile defaultParams 
  cleanUp 
  putStrLn "*********************************"
  putStrLn " Ok, things seem to work.  Enjoy!"
  putStrLn "*********************************"

  -- Don't assume SBV is installed.
  -- putStrLn "Check equivalence:"
  -- putStrLn ""
  -- putStrLn ""
  -- reify spec >>= 
  --   C.genCBMC C.defaultParams {C.numIterations = 20}

--------------------------------------------------------------------------------

cleanUp :: IO ()
cleanUp = do
  removeFile "copilot.c"
  removeFile "copilot.h"
  return ()