@@ -159,24 +159,30 @@ struct
159159 location : Location .t ;
160160 value : string ;
161161 format : string ;
162+ labels : string list option ;
162163 }
163164 [@@ deriving eq , ord , hash ]
164165
165166 let invariant_type = " loop_invariant"
166167
167- let to_yaml' {location; value; format} =
168+ let to_yaml' {location; value; format; labels } =
168169 [
169170 (" location" , Location. to_yaml location);
170171 (" value" , `String value);
171172 (" format" , `String format);
172- ]
173+ ] @ match labels with
174+ | Some labels -> [
175+ (" labels" , `A (List. map (fun label -> `String label) labels));
176+ ]
177+ | None -> []
173178
174179 let of_yaml y =
175180 let open GobYaml in
176181 let + location = y |> find " location" >> = Location. of_yaml
177182 and + value = y |> find " value" >> = to_string
178- and + format = y |> find " format" >> = to_string in
179- {location; value; format}
183+ and + format = y |> find " format" >> = to_string
184+ and + labels = y |> Yaml.Util. find " labels" >> = option_map (fun y -> y |> list >> = list_map to_string) in
185+ {location; value; format; labels}
180186 end
181187
182188 module LocationInvariant =
@@ -186,6 +192,20 @@ struct
186192 let invariant_type = " location_invariant"
187193 end
188194
195+ module LoopTransitionInvariant =
196+ struct
197+ include LoopInvariant
198+
199+ let invariant_type = " loop_transition_invariant"
200+ end
201+
202+ module LocationTransitionInvariant =
203+ struct
204+ include LoopTransitionInvariant
205+
206+ let invariant_type = " location_transition_invariant"
207+ end
208+
189209 module FlowInsensitiveInvariant =
190210 struct
191211 type t = {
@@ -215,17 +235,23 @@ struct
215235 type t =
216236 | LocationInvariant of LocationInvariant .t
217237 | LoopInvariant of LoopInvariant .t
238+ | LoopTransitionInvariant of LoopTransitionInvariant .t
239+ | LocationTransitionInvariant of LocationTransitionInvariant .t
218240 | FlowInsensitiveInvariant of FlowInsensitiveInvariant .t
219241 [@@ deriving eq , ord , hash ]
220242
221243 let invariant_type = function
222244 | LocationInvariant _ -> LocationInvariant. invariant_type
223245 | LoopInvariant _ -> LoopInvariant. invariant_type
246+ | LoopTransitionInvariant _ -> LoopTransitionInvariant. invariant_type
247+ | LocationTransitionInvariant _ -> LocationTransitionInvariant. invariant_type
224248 | FlowInsensitiveInvariant _ -> FlowInsensitiveInvariant. invariant_type
225249
226250 let to_yaml' = function
227251 | LocationInvariant x -> LocationInvariant. to_yaml' x
228252 | LoopInvariant x -> LoopInvariant. to_yaml' x
253+ | LoopTransitionInvariant x -> LoopTransitionInvariant. to_yaml' x
254+ | LocationTransitionInvariant x -> LocationTransitionInvariant. to_yaml' x
229255 | FlowInsensitiveInvariant x -> FlowInsensitiveInvariant. to_yaml' x
230256
231257 let of_yaml y =
@@ -237,6 +263,12 @@ struct
237263 else if invariant_type = LoopInvariant. invariant_type then
238264 let + x = y |> LoopInvariant. of_yaml in
239265 LoopInvariant x
266+ else if invariant_type = LoopTransitionInvariant. invariant_type then
267+ let + x = y |> LoopTransitionInvariant. of_yaml in
268+ LoopTransitionInvariant x
269+ else if invariant_type = LocationTransitionInvariant. invariant_type then
270+ let + x = y |> LocationTransitionInvariant. of_yaml in
271+ LocationTransitionInvariant x
240272 else if invariant_type = FlowInsensitiveInvariant. invariant_type then
241273 let + x = y |> FlowInsensitiveInvariant. of_yaml in
242274 FlowInsensitiveInvariant x
@@ -251,6 +283,8 @@ struct
251283 }
252284 [@@ deriving eq , ord , hash ]
253285
286+ let invariant_kind = " invariant"
287+
254288 let to_yaml {invariant_type} =
255289 `O [
256290 (" invariant" , `O ([
@@ -265,19 +299,132 @@ struct
265299 {invariant_type}
266300 end
267301
302+ module FunctionContract =
303+ struct
304+ type t = {
305+ location : Location .t ;
306+ requires : string ;
307+ ensures : string ;
308+ format : string ;
309+ labels : string list option ;
310+ }
311+ [@@ deriving eq , ord , hash ]
312+
313+ let contract_type = " function_contract"
314+
315+ let to_yaml' {location; requires; ensures; format; labels} =
316+ [
317+ (" location" , Location. to_yaml location);
318+ (" requires" , `String requires);
319+ (" ensures" , `String ensures);
320+ (" format" , `String format);
321+ ] @ match labels with
322+ | Some labels -> [
323+ (" labels" , `A (List. map (fun label -> `String label) labels));
324+ ]
325+ | None -> []
326+
327+ let of_yaml y =
328+ let open GobYaml in
329+ let + location = y |> find " location" >> = Location. of_yaml
330+ and + requires = y |> find " requires" >> = to_string
331+ and + ensures = y |> find " ensures" >> = to_string
332+ and + format = y |> find " format" >> = to_string
333+ and + labels = y |> Yaml.Util. find " labels" >> = option_map (fun y -> y |> list >> = list_map to_string) in
334+ {location; requires; ensures; format; labels}
335+ end
336+
337+ (* TODO: could maybe use GADT, but adds ugly existential layer to entry type pattern matching *)
338+ module ContractType =
339+ struct
340+ type t =
341+ | FunctionContract of FunctionContract .t
342+ [@@ deriving eq , ord , hash ]
343+
344+ let contract_type = function
345+ | FunctionContract _ -> FunctionContract. contract_type
346+
347+ let to_yaml' = function
348+ | FunctionContract x -> FunctionContract. to_yaml' x
349+
350+ let of_yaml y =
351+ let open GobYaml in
352+ let * contract_type = y |> find " type" >> = to_string in
353+ if contract_type = FunctionContract. contract_type then
354+ let + x = y |> FunctionContract. of_yaml in
355+ FunctionContract x
356+ else
357+ Error (`Msg " type" )
358+ end
359+
360+ module Contract =
361+ struct
362+ type t = {
363+ contract_type : ContractType .t ;
364+ }
365+ [@@ deriving eq , ord , hash ]
366+
367+ let invariant_kind = " contract"
368+
369+ let to_yaml {contract_type} =
370+ `O [
371+ (" contract" , `O ([
372+ (" type" , `String (ContractType. contract_type contract_type));
373+ ] @ ContractType. to_yaml' contract_type)
374+ )
375+ ]
376+
377+ let of_yaml y =
378+ let open GobYaml in
379+ let + contract_type = y |> find " contract" >> = ContractType. of_yaml in
380+ {contract_type}
381+ end
382+
383+ module InvariantKind =
384+ struct
385+ type t =
386+ | Invariant of Invariant .t
387+ | Contract of Contract .t
388+ [@@ deriving eq , ord , hash ]
389+
390+ let invariant_kind = function
391+ | Invariant _ -> Invariant. invariant_kind
392+ | Contract _ -> Contract. invariant_kind
393+
394+ let to_yaml = function
395+ | Invariant x -> Invariant. to_yaml x
396+ | Contract x -> Contract. to_yaml x
397+
398+ let of_yaml y =
399+ let open GobYaml in
400+ let * entries = y |> entries in
401+ match entries with
402+ | [(invariant_kind, _)] ->
403+ if invariant_kind = Invariant. invariant_kind then
404+ let + x = y |> Invariant. of_yaml in
405+ Invariant x
406+ else if invariant_kind = Contract. invariant_kind then
407+ let + x = y |> Contract. of_yaml in
408+ Contract x
409+ else
410+ Error (`Msg " kind" )
411+ | _ ->
412+ Error (`Msg " kind" )
413+ end
414+
268415 type t = {
269- content : Invariant .t list ;
416+ content : InvariantKind .t list ;
270417 }
271418 [@@ deriving eq , ord , hash ]
272419
273420 let entry_type = " invariant_set"
274421
275422 let to_yaml' {content} =
276- [(" content" , `A (List. map Invariant . to_yaml content))]
423+ [(" content" , `A (List. map InvariantKind . to_yaml content))]
277424
278425 let of_yaml y =
279426 let open GobYaml in
280- let + content = y |> find " content" >> = list >> = list_map Invariant . of_yaml in
427+ let + content = y |> find " content" >> = list >> = list_map InvariantKind . of_yaml in
281428 {content}
282429end
283430
0 commit comments