Skip to content

Commit d939de5

Browse files
committed
copilot-theorem: Support translating UpdateField to what4. Refs #524.
A new kind of `Op2`, called `UpdateField`, was added to `copilot-core` in a prior commit to support defining streams with updates to struct fields. This commit extends `copilot-theorem` to support reasoning about streams involving struct updates. We do so by providing a new case for the operation that translates a `copilot-core` `UpdateField` into a What4 representations of a Copilot expression. The implementation proves relatively straightforward, as struct field accessors always correspond to a concrete index value, which can then be used to update the value at the corresponding index in the list of struct fields.
1 parent 6034e6d commit d939de5

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

copilot-theorem/src/Copilot/Theorem/What4/Translate.hs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,8 @@ translateOp2 sym origExpr op xe1 xe2 = case (op, xe1, xe2) of
799799
(CE.BwShiftL _ _, xe1, xe2) -> translateBwShiftL xe1 xe2
800800
(CE.BwShiftR _ _, xe1, xe2) -> translateBwShiftR xe1 xe2
801801
(CE.Index _, xe1, xe2) -> translateIndex xe1 xe2
802+
(CE.UpdateField atp _ftp extractor, structXe, fieldXe) ->
803+
translateUpdateField atp extractor structXe fieldXe
802804
where
803805
-- Translate an 'CE.Add' operation and its arguments into a what4
804806
-- representation of the appropriate type.
@@ -964,6 +966,55 @@ translateOp2 sym origExpr op xe1 xe2 = case (op, xe1, xe2) of
964966
liftIO $ buildIndexExpr sym ix xes
965967
_ -> unexpectedValues "index operation"
966968

969+
-- Translate an 'CE.UpdateField' operation and its arguments into a what4
970+
-- representation. This function will panic if one of the following does not
971+
-- hold:
972+
--
973+
-- - The argument is not a struct.
974+
--
975+
-- - The struct's field cannot be found.
976+
translateUpdateField :: forall struct s.
977+
KnownSymbol s
978+
=> CT.Type struct
979+
-- ^ The type of the struct argument
980+
-> (struct -> CT.Field s b)
981+
-- ^ Extract a struct field
982+
-> XExpr sym
983+
-- ^ The first argument value (should be a struct)
984+
-> XExpr sym
985+
-- ^ The second argument value (should be the same type
986+
-- as the struct field)
987+
-> TransM sym (XExpr sym)
988+
-- ^ The first argument value, but with an updated
989+
-- value for the supplied field.
990+
translateUpdateField structTp extractor structXe newFieldXe =
991+
case (structTp, structXe) of
992+
(CT.Struct s, XStruct structFieldXes) ->
993+
case mIx s of
994+
Just ix -> return $ XStruct $ updateAt ix newFieldXe structFieldXes
995+
Nothing ->
996+
panic [ "Could not find field " ++ show fieldNameRepr
997+
, show s
998+
]
999+
_ -> unexpectedValues "update-field operation"
1000+
where
1001+
-- Update an element of a list at a particular index. This assumes the
1002+
-- preconditions that the index is a non-negative number that is less
1003+
-- than the length of the list.
1004+
updateAt :: forall a. Int -> a -> [a] -> [a]
1005+
updateAt _ _ [] = []
1006+
updateAt 0 new (_:xs) = new : xs
1007+
updateAt n new (x:xs) = x : updateAt (n-1) new xs
1008+
1009+
fieldNameRepr :: SymbolRepr s
1010+
fieldNameRepr = fieldName (extractor undefined)
1011+
1012+
structFieldNameReprs :: CT.Struct struct => struct -> [Some SymbolRepr]
1013+
structFieldNameReprs s = valueName <$> CT.toValues s
1014+
1015+
mIx :: CT.Struct struct => struct -> Maybe Int
1016+
mIx s = elemIndex (Some fieldNameRepr) (structFieldNameReprs s)
1017+
9671018
-- Check the types of the arguments. If the arguments are bitvector values,
9681019
-- apply the 'BVOp2'. If the arguments are floating-point values, apply the
9691020
-- 'FPOp2'. Otherwise, 'panic'.

0 commit comments

Comments
 (0)