Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example demonstrating struct update support. Refs #57. #70

Merged
merged 2 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions copilot-verifier/CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
2024-09-09
* Support verifying programs that use array updates. (#63)
* Support verifying programs that use struct updates. (#57)

2024-08-03
* Support building with `crucible-llvm-0.7` and `crux-llvm-0.9`. (#64)
Expand Down
1 change: 1 addition & 0 deletions copilot-verifier/copilot-verifier.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ library copilot-verifier-examples
Copilot.Verifier.Examples.ShouldPass.Partial.SubSignedWrap
Copilot.Verifier.Examples.ShouldPass.Structs
Copilot.Verifier.Examples.ShouldPass.UpdateArray
Copilot.Verifier.Examples.ShouldPass.UpdateStruct
Copilot.Verifier.Examples.ShouldPass.Voting
Copilot.Verifier.Examples.ShouldPass.WCV

Expand Down
2 changes: 2 additions & 0 deletions copilot-verifier/examples/Copilot/Verifier/Examples.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import qualified Copilot.Verifier.Examples.ShouldPass.Partial.ShiftRTooLarge a
import qualified Copilot.Verifier.Examples.ShouldPass.Partial.SubSignedWrap as Pass.SubSignedWrap
import qualified Copilot.Verifier.Examples.ShouldPass.Structs as Structs
import qualified Copilot.Verifier.Examples.ShouldPass.UpdateArray as UpdateArray
import qualified Copilot.Verifier.Examples.ShouldPass.UpdateStruct as UpdateStruct
import qualified Copilot.Verifier.Examples.ShouldPass.Voting as Voting
import qualified Copilot.Verifier.Examples.ShouldPass.WCV as WCV

Expand Down Expand Up @@ -74,6 +75,7 @@ shouldPassExamples verb = Map.fromList
, example "IntOps" (IntOps.verifySpec verb)
, example "Structs" (Structs.verifySpec verb)
, example "UpdateArray" (UpdateArray.verifySpec verb)
, example "UpdateStruct" (UpdateStruct.verifySpec verb)
, example "Voting" (Voting.verifySpec verb)
, example "WCV" (WCV.verifySpec verb)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE DataKinds #-}

-- | An example showing of using @copilot-verifier@ to verify a specification
-- involving structs where individual fields are updated.
module Copilot.Verifier.Examples.ShouldPass.UpdateStruct where

import Language.Copilot
import Copilot.Compile.C99
import Copilot.Verifier ( Verbosity, VerifierOptions(..)
, defaultVerifierOptions, verifyWithOptions )

-- | Definition for `Volts`.
data Volts = Volts
{ numVolts :: Field "numVolts" Word32
, flag :: Field "flag" Bool
}

-- | `Struct` instance for `Volts`.
instance Struct Volts where
typeName _ = "volts"
toValues vlts = [ Value Word32 (numVolts vlts)
, Value Bool (flag vlts)
]

-- | `Volts` instance for `Typed`.
instance Typed Volts where
typeOf = Struct (Volts (Field 0) (Field False))

data Battery = Battery
{ temp :: Field "temp" Word32
, volts :: Field "volts" (Array 10 Volts)
, other :: Field "other" (Array 10 (Array 5 Word32))
}

-- | `Battery` instance for `Struct`.
instance Struct Battery where
typeName _ = "battery"
toValues battery = [ Value typeOf (temp battery)
, Value typeOf (volts battery)
, Value typeOf (other battery)
]

-- | `Battery` instance for `Typed`. Note that `undefined` is used as an
-- argument to `Field`. This argument is never used, so `undefined` will never
-- throw an error.
instance Typed Battery where
typeOf = Struct (Battery (Field 0) (Field undefined) (Field undefined))

spec :: Spec
spec = do
let battery :: Stream Battery
battery = extern "battery" Nothing

-- Update a struct field, then check it for equality.
trigger "updateTrig"
((battery ## temp =$ (+1))#temp == (battery#temp + 1))
[arg battery]

verifySpec :: Verbosity -> IO ()
verifySpec verb = reify spec >>= verifyWithOptions defaultVerifierOptions{verbosity = verb}
mkDefaultCSettings [] "updateStruct"
Loading