-
Notifications
You must be signed in to change notification settings - Fork 33
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
feat: get-assignment statement #848
Changes from 7 commits
ec769f9
a6221a4
b465653
c9317ef
fe5c2cb
9b461ef
0cfbec6
f5cc809
5c6f05f
083693f
541b4d6
86f8f33
9cbf833
15f0560
9c79109
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -95,6 +95,52 @@ let enable_maxsmt b = | |||||
else | ||||||
DStd.Extensions.Smtlib2.(disable maxsmt) | ||||||
|
||||||
(* Dolmen util *) | ||||||
|
||||||
(** Returns the list of terms inside a dolmen binder. *) | ||||||
let terms_of_dolmen_binder = function | ||||||
| DStd.Expr.Let_seq l | Let_par l -> | ||||||
List.map snd l | ||||||
| Lambda _ | Exists _ | Forall _ -> [] | ||||||
|
||||||
(** Adds the named terms of the term [term] to the map accumulator [acc] *) | ||||||
let get_named_of_term | ||||||
(acc : DStd.Expr.term Util.MS.t) | ||||||
(term : DStd.Expr.term) = | ||||||
let rec loop acc terms_to_check = | ||||||
match terms_to_check with | ||||||
| [] -> acc | ||||||
| [] :: rest -> loop acc rest | ||||||
| (term :: tl) :: rest -> | ||||||
let terms_to_check = tl :: rest in | ||||||
let terms_to_check = | ||||||
match term.DStd.Expr.term_descr with | ||||||
| DStd.Expr.Var _ | Cst _ -> terms_to_check | ||||||
| App (t, _, tl) -> (t :: tl) :: terms_to_check | ||||||
| Binder (b, t) -> | ||||||
(t :: terms_of_dolmen_binder b) :: terms_to_check | ||||||
| Match (t, plt) -> (t :: (List.map snd plt)) :: terms_to_check | ||||||
in | ||||||
match DStd.Expr.Term.get_tag term DStd.Expr.Tags.named with | ||||||
| None -> loop acc terms_to_check | ||||||
| Some name -> loop (Util.MS.add name term acc) terms_to_check | ||||||
in | ||||||
loop acc [[term]] | ||||||
|
||||||
(** Adds the named terms of the statement [stmt] to the map accumulator [acc] *) | ||||||
let get_named_of_stmt | ||||||
~(acc : DStd.Expr.term Util.MS.t) | ||||||
(stmt : Typer_Pipe.typechecked D_loop.Typer_Pipe.stmt) = | ||||||
match stmt.contents with | ||||||
| `Hyp f | `Goal f -> get_named_of_term acc f | ||||||
| `Clause l -> List.fold_left get_named_of_term acc l | ||||||
| `Solve (l1, l2) -> | ||||||
List.fold_left | ||||||
get_named_of_term | ||||||
(List.fold_left get_named_of_term acc l1) | ||||||
l2 | ||||||
| _ -> acc | ||||||
|
||||||
(* We currently use the full state of the solver as model. *) | ||||||
type model = Model : 'a sat_module * 'a -> model | ||||||
|
||||||
|
@@ -297,6 +343,14 @@ let main () = | |||||
State.create_key ~pipe:"" "optimize" | ||||||
in | ||||||
|
||||||
let get_assignment: bool State.key = | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be called |
||||||
State.create_key ~pipe:"" "get_assignment" | ||||||
in | ||||||
|
||||||
let named_terms: DStd.Expr.term Util.MS.t State.key = | ||||||
State.create_key ~pipe:"" "named_terms" | ||||||
in | ||||||
|
||||||
let debug_parsed_pipe st c = | ||||||
if State.get State.debug st then | ||||||
Format.eprintf "[logic][parsed][%a] @[<hov>%a@]@." | ||||||
|
@@ -409,6 +463,8 @@ let main () = | |||||
|> State.set solver_ctx_key solver_ctx | ||||||
|> State.set partial_model_key partial_model | ||||||
|> State.set optimize_key (O.get_optimize ()) | ||||||
|> State.set get_assignment false | ||||||
|> State.set named_terms Util.MS.empty | ||||||
|> State.init ~debug ~report_style ~reports ~max_warn ~time_limit | ||||||
~size_limit ~response_file | ||||||
|> Parser.init | ||||||
|
@@ -536,10 +592,18 @@ let main () = | |||||
solver; | ||||||
st | ||||||
) | ||||||
| ":produce-assignments", Symbol { name = Simple b; _ } -> | ||||||
begin | ||||||
match bool_of_string_opt b with | ||||||
| None -> | ||||||
print_wrn_opt ~name:":verbosity" st_loc "integer" value; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
st | ||||||
| Some b -> | ||||||
State.set get_assignment b st | ||||||
end | ||||||
| (":global-declarations" | ||||||
| ":interactive-mode" | ||||||
| ":produce-assertions" | ||||||
| ":produce-assignments" | ||||||
| ":produce-proofs" | ||||||
| ":produce-unsat-assumptions" | ||||||
| ":print-success" | ||||||
|
@@ -650,13 +714,58 @@ let main () = | |||||
unsupported_opt name | ||||||
in | ||||||
|
||||||
(* Fetches the term value in the current model. *) | ||||||
let evaluate_term get_value name term = | ||||||
let ae_form = | ||||||
D_cnf.make_form | ||||||
name | ||||||
term | ||||||
Loc.dummy | ||||||
~decl_kind:Expr.Dgoal | ||||||
in | ||||||
match get_value ae_form with | ||||||
| None -> "unknown" (* Not in the standard, but useful for recording when | ||||||
Alt-Ergo fails to guess the value of a term. *) | ||||||
| Some v -> Fmt.to_to_string Expr.print v | ||||||
in | ||||||
|
||||||
let print_terms_assignments = | ||||||
Fmt.list | ||||||
~sep:(fun fmt _ -> Fmt.pf fmt "@,") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Missed it earlier but |
||||||
(fun fmt (name, v) -> Fmt.pf fmt "(%s %s)" name v) | ||||||
in | ||||||
|
||||||
let handle_get_assignment ~get_value st = | ||||||
let assignments = | ||||||
Util.MS.fold | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: you can probably leverage There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I preferred to build the list and print it afterwards to make the code more readable |
||||||
(fun name term acc -> | ||||||
if DStd.Expr.Ty.equal term.DStd.Expr.term_ty DStd.Expr.Ty.bool then | ||||||
(name, evaluate_term get_value name term) :: acc | ||||||
else | ||||||
acc | ||||||
) | ||||||
(State.get named_terms st) | ||||||
[] | ||||||
in | ||||||
Printer.print_std | ||||||
"(@[<v 0>%a@])@," | ||||||
print_terms_assignments | ||||||
assignments | ||||||
in | ||||||
|
||||||
let handle_stmt : | ||||||
Frontend.used_context -> State.t -> | ||||||
_ D_loop.Typer_Pipe.stmt -> State.t = | ||||||
let goal_cnt = ref 0 in | ||||||
fun all_context st td -> | ||||||
let file_loc = (State.get State.logic_file st).loc in | ||||||
let solver_ctx = State.get solver_ctx_key st in | ||||||
let st = | ||||||
let named_terms_map = | ||||||
get_named_of_stmt ~acc:(State.get named_terms st) td | ||||||
in | ||||||
State.set named_terms named_terms_map st | ||||||
in | ||||||
match td with | ||||||
(* When the next statement is a goal, the solver is called and provided | ||||||
the goal and the current context *) | ||||||
|
@@ -763,6 +872,8 @@ let main () = | |||||
|> State.set partial_model_key None | ||||||
|> State.set solver_ctx_key empty_solver_ctx | ||||||
|> State.set optimize_key (O.get_optimize ()) | ||||||
|> State.set get_assignment false | ||||||
|> State.set named_terms Util.MS.empty | ||||||
|
||||||
| {contents = `Exit; _} -> raise Exit | ||||||
|
||||||
|
@@ -778,6 +889,35 @@ let main () = | |||||
handle_get_info st kind; | ||||||
st | ||||||
|
||||||
| {contents = `Get_assignment; _} -> | ||||||
begin | ||||||
match State.get partial_model_key st with | ||||||
| Some Model ((module SAT), partial_model) -> | ||||||
begin | ||||||
match SAT.get_model partial_model with | ||||||
| Some _ -> | ||||||
if State.get get_assignment st then | ||||||
handle_get_assignment | ||||||
~get_value:(SAT.get_value partial_model) | ||||||
st | ||||||
else | ||||||
recoverable_error | ||||||
"Produce assignments disabled; \ | ||||||
add (set-option :produce-assignments true)"; | ||||||
st | ||||||
| _ -> | ||||||
recoverable_error | ||||||
"Model generation disactivated, cannot execute \ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although do we actually need this case? It looks like we don't care about the result of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The command should only be available in SAT mode, is that the good way to check it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As the name indicates, the |
||||||
get-assignment."; | ||||||
st | ||||||
end | ||||||
| None -> | ||||||
(* TODO: add the location of the statement. *) | ||||||
recoverable_error | ||||||
"No model produced, cannot execute get-assignment."; | ||||||
st | ||||||
end | ||||||
|
||||||
| {contents = `Other (custom, args); _} -> | ||||||
handle_custom_statement custom args st | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,5 @@ | |
unknown | ||
( | ||
) | ||
() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this going to do the right thing wrt capture of bound variables (e.g. what happens if I do
(let ((x 2)) (+ (! x :named name)))
)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not think about the semantics of named terms in bindings. Do you think we should not record the named formulas in bindings for now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't have an easy way of checking capture avoidance then yes, that would be better (this is already what we do for quantifiers if I am not mistaken).