let join = String.concat " "
let structure name constructor fields =
let width = List.fold_left (fun sum (_, _, size) -> sum + size) 0 fields in
let arguments = join (List.map (fun (field, kind, _) -> Printf.sprintf "(%s %s)" field kind) fields) in
let values = join (List.map (fun (field, _, _) -> field) fields) in
let high = ref (width - 1) in
let selectors = List.map (fun (field, kind, size) ->
let low = !high - size + 1 in
let result = Printf.sprintf
"(define-fun %s ((cells %s)) %s ((_ extract %d %d) cells))" field name kind !high low in
high := low - 1;
result) fields in
[Printf.sprintf "(define-sort %s () (_ BitVec %d))" name width;
Printf.sprintf "(define-fun %s (%s) %s (concat %s))" constructor arguments name values] @ selectors
let record name prefix element count size =
let fields = List.init count (fun i -> Printf.sprintf "%s%d" prefix i, element, size) in
let lines = structure name prefix fields in
let value = ref (Printf.sprintf "(%s%d cells)" prefix (count - 1)) in
for i = count - 2 downto 0 do
value := Printf.sprintf "(ite (= i #x%02x) (%s%d cells) %s)" i prefix i !value
done;
let fields = List.init count (fun i ->
Printf.sprintf "(ite (= i #x%02x) v (%s%d cells))" i prefix i) in
lines @ [Printf.sprintf "(define-fun at ((cells %s) (i Index)) %s\n %s)" name element !value;
Printf.sprintf "(define-fun update ((cells %s) (i Index) (v %s)) %s\n (%s %s))"
name element name prefix (join fields)]
let generate ~timeout =
if timeout <= 0 then invalid_arg "timeout must be positive";
let lines = ["(set-logic QF_BV)"; "(set-option :produce-models true)";
Printf.sprintf "(set-option :timeout %d)" timeout;
"(define-sort Index () (_ BitVec 8))"; "(define-sort Word () (_ BitVec 64))"] @
record "Slots" "indices" "Index" 16 8 @
record "Words" "words" "Word" 16 64 @
record "Queues" "queues" "Words" 2 1024 @
record "Positions" "positions" "Slots" 2 128 @
structure "State" "state" [
"memory", "Words", 1024; "registers", "Words", 1024;
"counters", "Slots", 128; "heads", "Slots", 128; "tails", "Slots", 128;
"addresses", "Positions", 256; "values", "Queues", 2048;
"positions", "Positions", 256; "critical", "Slots", 128] in
let constants = List.map (fun (name, kind, constructor, value, count) ->
Printf.sprintf "(define-fun %s () %s\n (%s %s))" name kind constructor
(join (List.init count (fun _ -> value)))) [
"zeros", "Words", "words", "#x0000000000000000", 16;
"slots", "Slots", "indices", "#x00", 16;
"absent", "Slots", "indices", "#xff", 16;
"emptyqueues", "Queues", "queues", "zeros", 2;
"emptypositions", "Positions", "positions", "slots", 2;
"unseen", "Positions", "positions", "absent", 2] in
String.concat "\n\n" (lines @ constants) ^ "\n"