mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-10 21:24:06 -05:00
feat: show_trace, and trace_reader, can now display a QF_UF trace
the trace can contain assertions.
This commit is contained in:
parent
3aadc640c4
commit
96dddb5383
15 changed files with 161 additions and 22 deletions
|
|
@ -42,3 +42,14 @@ let th_bool_static : Solver.theory = Th_bool.theory_static
|
||||||
let th_data : Solver.theory = Th_data.theory
|
let th_data : Solver.theory = Th_data.theory
|
||||||
let th_lra : Solver.theory = Th_lra.theory
|
let th_lra : Solver.theory = Th_lra.theory
|
||||||
let th_ty_unin : Solver.theory = Th_ty_unin.theory
|
let th_ty_unin : Solver.theory = Th_ty_unin.theory
|
||||||
|
|
||||||
|
(** All constant decoders *)
|
||||||
|
let const_decoders =
|
||||||
|
List.flatten
|
||||||
|
[
|
||||||
|
Uconst.const_decoders;
|
||||||
|
LRA_term.const_decoders;
|
||||||
|
Ty.const_decoders;
|
||||||
|
(* TODO Th_data *)
|
||||||
|
Form.const_decoders;
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ let const_decoders : Const.decoders =
|
||||||
ops,
|
ops,
|
||||||
Ser_decode.(
|
Ser_decode.(
|
||||||
fun dec_t ->
|
fun dec_t ->
|
||||||
let+ uc_id = ID.deser and+ uc_ty = dec_t in
|
let+ uc_id, uc_ty = tup2 ID.deser dec_t in
|
||||||
Uconst { uc_id; uc_ty }) );
|
Uconst { uc_id; uc_ty }) );
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ type const_decoders = Const.decoders
|
||||||
type t = {
|
type t = {
|
||||||
tst: Term.store;
|
tst: Term.store;
|
||||||
src: Tr.Source.t;
|
src: Tr.Source.t;
|
||||||
cache: (Term.t, string) result ID_cache.t;
|
cache: (Term.t, Dec.Error.t) result ID_cache.t;
|
||||||
mutable const_decode:
|
mutable const_decode:
|
||||||
(Const.Ops.t * (Term.t Dec.t -> Const.view Dec.t)) Util.Str_map.t;
|
(Const.Ops.t * (Term.t Dec.t -> Const.view Dec.t)) Util.Str_map.t;
|
||||||
(** tag -> const decoder *)
|
(** tag -> const decoder *)
|
||||||
|
|
@ -75,22 +75,32 @@ let decode_term (self : t) ~read_subterm ~tag : Term.t Dec.t =
|
||||||
let+ c_view = reflect_or_fail (c_dec read_subterm) view in
|
let+ c_view = reflect_or_fail (c_dec read_subterm) view in
|
||||||
let const = Const.make c_view ops ~ty in
|
let const = Const.make c_view ops ~ty in
|
||||||
Term.const self.tst const))
|
Term.const self.tst const))
|
||||||
| "Tf@" -> assert false (* TODO *)
|
| "Tf@" ->
|
||||||
|
Dec.(
|
||||||
|
let+ f = dict_field "f" read_subterm
|
||||||
|
and+ l = dict_field "l" (list read_subterm)
|
||||||
|
and+ acc0 = dict_field "a0" read_subterm in
|
||||||
|
Term.app_fold self.tst ~f l ~acc0)
|
||||||
| _ -> Dec.failf "unknown tag %S for a term" tag
|
| _ -> Dec.failf "unknown tag %S for a term" tag
|
||||||
|
|
||||||
let rec read_term (self : t) (id : term_ref) : _ result =
|
let rec read_term_err (self : t) (id : term_ref) : _ result =
|
||||||
(* decoder for subterms *)
|
(* decoder for subterms *)
|
||||||
let read_subterm : Term.t Dec.t =
|
let read_subterm : Term.t Dec.t =
|
||||||
Dec.(
|
Dec.(
|
||||||
let* id = int in
|
let* id = int in
|
||||||
match read_term self id with
|
return_result_err @@ read_term_err self id)
|
||||||
| Ok x -> return x
|
|
||||||
| Error e -> fail e)
|
|
||||||
in
|
in
|
||||||
|
|
||||||
ID_cache.get self.cache id ~compute:(fun id ->
|
ID_cache.get self.cache id ~compute:(fun id ->
|
||||||
match Tr.Source.get_entry self.src id with
|
match Tr.Source.get_entry self.src id with
|
||||||
| None -> Error (Printf.sprintf "invalid entry: %d" id)
|
| None ->
|
||||||
|
Error
|
||||||
|
(Dec.Error.of_string
|
||||||
|
(Printf.sprintf "invalid entry: %d" id)
|
||||||
|
(Ser_value.int id))
|
||||||
| Some (tag, v) ->
|
| Some (tag, v) ->
|
||||||
let dec = decode_term self ~tag ~read_subterm in
|
let dec = decode_term self ~tag ~read_subterm in
|
||||||
Dec.run dec v |> Result.map_error Dec.Error.to_string)
|
Dec.run dec v)
|
||||||
|
|
||||||
|
let read_term self id =
|
||||||
|
Result.map_error Dec.Error.to_string @@ read_term_err self id
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,4 @@ val create :
|
||||||
|
|
||||||
val add_const_decoders : t -> const_decoders -> unit
|
val add_const_decoders : t -> const_decoders -> unit
|
||||||
val read_term : t -> term_ref -> (Term.t, string) result
|
val read_term : t -> term_ref -> (Term.t, string) result
|
||||||
|
val read_term_err : t -> term_ref -> (Term.t, Ser_decode.Error.t) result
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,14 @@ let emit_term_ (self : state) (t : Term.t) =
|
||||||
in
|
in
|
||||||
V.dict_of_list fields )
|
V.dict_of_list fields )
|
||||||
| T.E_app_fold { f; args; acc0 } ->
|
| T.E_app_fold { f; args; acc0 } ->
|
||||||
"Tf@", V.(list [ loop' f; list (List.map loop' args); loop' acc0 ])
|
( "Tf@",
|
||||||
|
V.(
|
||||||
|
dict_of_list
|
||||||
|
[
|
||||||
|
"f", loop' f;
|
||||||
|
"l", list (List.map loop' args);
|
||||||
|
"a0", loop' acc0;
|
||||||
|
]) )
|
||||||
| T.E_lam (name, ty, bod) ->
|
| T.E_lam (name, ty, bod) ->
|
||||||
"Tl", V.(list [ string name; loop' ty; loop' bod ])
|
"Tl", V.(list [ string name; loop' ty; loop' bod ])
|
||||||
| T.E_pi (name, ty, bod) ->
|
| T.E_pi (name, ty, bod) ->
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,6 @@
|
||||||
(name show_trace)
|
(name show_trace)
|
||||||
(modules show_trace)
|
(modules show_trace)
|
||||||
(modes native)
|
(modes native)
|
||||||
(libraries containers sidekick.util sidekick.core sidekick.trace)
|
(libraries containers sidekick.util sidekick.core sidekick.trace
|
||||||
|
sidekick.smt-solver sidekick-base)
|
||||||
(flags :standard -safe-string -color always -open Sidekick_util))
|
(flags :standard -safe-string -color always -open Sidekick_util))
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,43 @@
|
||||||
|
open Sidekick_core
|
||||||
open Sidekick_trace
|
open Sidekick_trace
|
||||||
|
module Smt = Sidekick_smt_solver
|
||||||
|
|
||||||
let show_file file : unit =
|
let show_file ~dump file : unit =
|
||||||
Log.debugf 1 (fun k -> k "(@[show-file %S@])" file);
|
Log.debugf 1 (fun k -> k "(@[show-file %S@])" file);
|
||||||
let src = Source.of_string_using_bencode @@ CCIO.File.read_exn file in
|
let src = Source.of_string_using_bencode @@ CCIO.File.read_exn file in
|
||||||
|
let tst = Term.Store.create () in
|
||||||
|
|
||||||
|
(* trace reader *)
|
||||||
|
let t_reader =
|
||||||
|
Smt.Trace_reader.create tst src
|
||||||
|
~const_decoders:
|
||||||
|
[
|
||||||
|
Term.const_decoders; Box.const_decoders; Sidekick_base.const_decoders;
|
||||||
|
]
|
||||||
|
in
|
||||||
|
|
||||||
Source.iter_all src (fun i ~tag v ->
|
Source.iter_all src (fun i ~tag v ->
|
||||||
Format.printf "[%d]: %S %a@." i tag Sidekick_util.Ser_value.pp v)
|
Log.debugf 10 (fun k ->
|
||||||
|
k "(@[show-trace[%d]@ :tag %S@ :val %a@])" i tag Ser_value.pp v);
|
||||||
|
if dump then Format.printf "[%d]: %S %a@." i tag Ser_value.pp v;
|
||||||
|
|
||||||
|
match Smt.Trace_reader.decode t_reader ~tag v with
|
||||||
|
| Some e -> Fmt.printf "[%d]: %a@." i Smt.Trace_reader.pp_entry e
|
||||||
|
| None -> ())
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
let files = ref [] in
|
let files = ref [] in
|
||||||
|
let dump = ref false in
|
||||||
let opts =
|
let opts =
|
||||||
[
|
[
|
||||||
|
"--dump", Arg.Set dump, " dump each raw entry";
|
||||||
( "--bt",
|
( "--bt",
|
||||||
Arg.Unit (fun () -> Printexc.record_backtrace true),
|
Arg.Unit (fun () -> Printexc.record_backtrace true),
|
||||||
" enable backtraces" );
|
" enable backtraces" );
|
||||||
|
"-d", Arg.Int Log.set_debug, " debug level";
|
||||||
]
|
]
|
||||||
|> Arg.align
|
|> Arg.align
|
||||||
in
|
in
|
||||||
Arg.parse opts (fun f -> files := f :: !files) "show_trace [file]+";
|
Arg.parse opts (fun f -> files := f :: !files) "show_trace [file]+";
|
||||||
let files = List.rev !files in
|
let files = List.rev !files in
|
||||||
List.iter show_file files
|
List.iter (show_file ~dump:!dump) files
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ module Theory_id = Theory_id
|
||||||
module Preprocess = Preprocess
|
module Preprocess = Preprocess
|
||||||
module Find_foreign = Find_foreign
|
module Find_foreign = Find_foreign
|
||||||
module Tracer = Tracer
|
module Tracer = Tracer
|
||||||
|
module Trace_reader = Trace_reader
|
||||||
|
|
||||||
type theory = Theory.t
|
type theory = Theory.t
|
||||||
type solver = Solver.t
|
type solver = Solver.t
|
||||||
|
|
|
||||||
55
src/smt/trace_reader.ml
Normal file
55
src/smt/trace_reader.ml
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
open Sidekick_core
|
||||||
|
module Tr = Sidekick_trace
|
||||||
|
|
||||||
|
type entry = Assert of Term.t | Assert_clause of Lit.t list
|
||||||
|
|
||||||
|
let pp_entry out = function
|
||||||
|
| Assert t -> Fmt.fprintf out "(@[assert@ %a@])" Term.pp t
|
||||||
|
| Assert_clause c ->
|
||||||
|
Fmt.fprintf out "(@[assert-c@ %a@])" (Fmt.Dump.list Lit.pp) c
|
||||||
|
|
||||||
|
type t = { tst: Term.store; src: Tr.Source.t; t_dec: Term.Trace_reader.t }
|
||||||
|
|
||||||
|
let create ?const_decoders tst src : t =
|
||||||
|
let t_dec = Term.Trace_reader.create ?const_decoders tst ~source:src in
|
||||||
|
{ tst; src; t_dec }
|
||||||
|
|
||||||
|
let add_const_decoders self c = Term.Trace_reader.add_const_decoders self.t_dec c
|
||||||
|
|
||||||
|
let dec_t (self : t) =
|
||||||
|
Ser_decode.(
|
||||||
|
let* i = int in
|
||||||
|
return_result @@ Term.Trace_reader.read_term self.t_dec i)
|
||||||
|
|
||||||
|
let dec_c (self : t) =
|
||||||
|
Ser_decode.(
|
||||||
|
let dec_lit =
|
||||||
|
let+ b, t = tup2 bool @@ dec_t self in
|
||||||
|
Lit.atom self.tst ~sign:b t
|
||||||
|
in
|
||||||
|
list dec_lit)
|
||||||
|
|
||||||
|
let decode (self : t) ~tag v =
|
||||||
|
Log.debugf 30 (fun k ->
|
||||||
|
k "(@[trace-reader.decode@ :tag %S@ :val %a@])" tag Ser_value.pp v);
|
||||||
|
match tag with
|
||||||
|
| "Asst" ->
|
||||||
|
(match Ser_decode.(run (dec_t self) v) with
|
||||||
|
| Ok t -> Some (Assert t)
|
||||||
|
| Error err ->
|
||||||
|
Fmt.eprintf "cannot decode entry with tag %S:@ %a@." tag
|
||||||
|
Ser_decode.Error.pp err;
|
||||||
|
None)
|
||||||
|
| "AssC" ->
|
||||||
|
Ser_decode.(
|
||||||
|
(match run (dec_c self) v with
|
||||||
|
| Ok c -> Some (Assert_clause c)
|
||||||
|
| Error err ->
|
||||||
|
Fmt.eprintf "cannot decode entry with tag %S:@ %a@." tag
|
||||||
|
Ser_decode.Error.pp err;
|
||||||
|
None))
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let decode_entry self id : _ option =
|
||||||
|
let tag, v = Tr.Source.get_entry_exn self.src id in
|
||||||
|
decode self ~tag v
|
||||||
17
src/smt/trace_reader.mli
Normal file
17
src/smt/trace_reader.mli
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
(** Read trace *)
|
||||||
|
|
||||||
|
open Sidekick_core
|
||||||
|
module Tr = Sidekick_trace
|
||||||
|
|
||||||
|
type entry = Assert of Term.t | Assert_clause of Lit.t list
|
||||||
|
|
||||||
|
val pp_entry : entry Fmt.printer
|
||||||
|
|
||||||
|
type t
|
||||||
|
|
||||||
|
val create :
|
||||||
|
?const_decoders:Const.decoders list -> Term.store -> Tr.Source.t -> t
|
||||||
|
|
||||||
|
val add_const_decoders : t -> Const.decoders -> unit
|
||||||
|
val decode : t -> tag:string -> Ser_value.t -> entry option
|
||||||
|
val decode_entry : t -> Tr.Entry_id.t -> entry option
|
||||||
|
|
@ -2,8 +2,6 @@ open Sidekick_core
|
||||||
module Tr = Sidekick_trace
|
module Tr = Sidekick_trace
|
||||||
module V = Ser_value
|
module V = Ser_value
|
||||||
|
|
||||||
type Tr.entry_view += Assert of Term.t | Assert_clause of Lit.t list
|
|
||||||
|
|
||||||
class type t =
|
class type t =
|
||||||
object
|
object
|
||||||
inherit Term.Tracer.t
|
inherit Term.Tracer.t
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
open Sidekick_core
|
open Sidekick_core
|
||||||
module Tr = Sidekick_trace
|
module Tr = Sidekick_trace
|
||||||
|
|
||||||
type Tr.entry_view += Assert of Term.t | Assert_clause of Lit.t list
|
|
||||||
|
|
||||||
class type t =
|
class type t =
|
||||||
object
|
object
|
||||||
inherit Term.Tracer.t
|
inherit Term.Tracer.t
|
||||||
|
|
|
||||||
|
|
@ -24,18 +24,19 @@ let null : t =
|
||||||
end)
|
end)
|
||||||
|
|
||||||
let of_out_channel_using_bencode (oc : out_channel) : t =
|
let of_out_channel_using_bencode (oc : out_channel) : t =
|
||||||
let id_ = ref 0 in
|
(* id: offset in the channel *)
|
||||||
|
let off = ref 0 in
|
||||||
let buf = Buffer.create 128 in
|
let buf = Buffer.create 128 in
|
||||||
(module struct
|
(module struct
|
||||||
let emit ~tag (v : Ser_value.t) =
|
let emit ~tag (v : Ser_value.t) =
|
||||||
assert (Buffer.length buf = 0);
|
assert (Buffer.length buf = 0);
|
||||||
let id = Entry_id.of_int_unsafe !id_ in
|
let id = Entry_id.of_int_unsafe !off in
|
||||||
(* add tag+id around *)
|
(* add tag+id around *)
|
||||||
let v' = Ser_value.(list [ int id; string tag; v ]) in
|
let v' = Ser_value.(list [ int id; string tag; v ]) in
|
||||||
incr id_;
|
|
||||||
Sidekick_bencode.Encode.to_buffer buf v';
|
Sidekick_bencode.Encode.to_buffer buf v';
|
||||||
Buffer.add_char buf '\n';
|
Buffer.add_char buf '\n';
|
||||||
Buffer.output_buffer oc buf;
|
Buffer.output_buffer oc buf;
|
||||||
|
off := !off + Buffer.length buf;
|
||||||
Buffer.clear buf;
|
Buffer.clear buf;
|
||||||
id
|
id
|
||||||
end)
|
end)
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,11 @@ module Error = struct
|
||||||
type t = { msg: string; v: V.t; subs: t list }
|
type t = { msg: string; v: V.t; subs: t list }
|
||||||
|
|
||||||
let mk ?(subs = []) msg v : t = { msg; v; subs }
|
let mk ?(subs = []) msg v : t = { msg; v; subs }
|
||||||
|
let of_string s v : t = mk s v
|
||||||
|
|
||||||
let pp out (self : t) =
|
let pp out (self : t) =
|
||||||
let rec pp out self =
|
let rec pp out self =
|
||||||
Fmt.fprintf out "@[<v2>@[<2>%s@ in %a@]" self.msg V.pp self.v;
|
Fmt.fprintf out "@[<v2>@[<2>%s@ in value %a@]" self.msg V.pp self.v;
|
||||||
List.iter
|
List.iter
|
||||||
(fun s -> Fmt.fprintf out "@ @[<2>sub-error:@ %a@]" pp s)
|
(fun s -> Fmt.fprintf out "@ @[<2>sub-error:@ %a@]" pp s)
|
||||||
self.subs;
|
self.subs;
|
||||||
|
|
@ -28,10 +29,19 @@ type 'a t = { deser: V.t -> 'a } [@@unboxed]
|
||||||
|
|
||||||
let[@inline] fail_ msg v = raise_notrace (Fail (Error.mk msg v))
|
let[@inline] fail_ msg v = raise_notrace (Fail (Error.mk msg v))
|
||||||
let[@inline] fail_e e = raise_notrace (Fail e)
|
let[@inline] fail_e e = raise_notrace (Fail e)
|
||||||
|
let fail_err e = { deser = (fun _ -> fail_e e) }
|
||||||
let return x = { deser = (fun _ -> x) }
|
let return x = { deser = (fun _ -> x) }
|
||||||
let fail s = { deser = (fun v -> fail_ s v) }
|
let fail s = { deser = (fun v -> fail_ s v) }
|
||||||
let failf fmt = Printf.ksprintf fail fmt
|
let failf fmt = Printf.ksprintf fail fmt
|
||||||
|
|
||||||
|
let return_result = function
|
||||||
|
| Ok x -> return x
|
||||||
|
| Error s -> fail s
|
||||||
|
|
||||||
|
let return_result_err = function
|
||||||
|
| Ok x -> return x
|
||||||
|
| Error e -> fail_err e
|
||||||
|
|
||||||
let unwrap_opt msg = function
|
let unwrap_opt msg = function
|
||||||
| Some x -> return x
|
| Some x -> return x
|
||||||
| None -> fail msg
|
| None -> fail msg
|
||||||
|
|
@ -43,6 +53,8 @@ let bool =
|
||||||
deser =
|
deser =
|
||||||
(function
|
(function
|
||||||
| V.Bool b -> b
|
| V.Bool b -> b
|
||||||
|
| V.Int 1 -> true
|
||||||
|
| V.Int 0 -> false
|
||||||
| v -> fail_ "expected bool" v);
|
| v -> fail_ "expected bool" v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ module Error : sig
|
||||||
include Sidekick_sigs.PRINT with type t := t
|
include Sidekick_sigs.PRINT with type t := t
|
||||||
|
|
||||||
val to_string : t -> string
|
val to_string : t -> string
|
||||||
|
|
||||||
|
val of_string : string -> Ser_value.t -> t
|
||||||
end
|
end
|
||||||
|
|
||||||
(** {2 Main combinators *)
|
(** {2 Main combinators *)
|
||||||
|
|
@ -20,8 +22,11 @@ val int : int t
|
||||||
val bool : bool t
|
val bool : bool t
|
||||||
val string : string t
|
val string : string t
|
||||||
val return : 'a -> 'a t
|
val return : 'a -> 'a t
|
||||||
|
val return_result : ('a, string) result -> 'a t
|
||||||
|
val return_result_err : ('a, Error.t) result -> 'a t
|
||||||
val fail : string -> 'a t
|
val fail : string -> 'a t
|
||||||
val failf : ('a, unit, string, 'b t) format4 -> 'a
|
val failf : ('a, unit, string, 'b t) format4 -> 'a
|
||||||
|
val fail_err : Error.t -> 'a t
|
||||||
val unwrap_opt : string -> 'a option -> 'a t
|
val unwrap_opt : string -> 'a option -> 'a t
|
||||||
(** Unwrap option, or fail *)
|
(** Unwrap option, or fail *)
|
||||||
val any : Ser_value.t t
|
val any : Ser_value.t t
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue