2022-01-18 20:51:02 +03:00
|
|
|
(* This file is part of the Catala compiler, a specification language for tax
|
|
|
|
and social benefits computation rules. Copyright (C) 2022 Inria, contributor:
|
2022-01-18 20:59:05 +03:00
|
|
|
Aymeric Fromherz <aymeric.fromherz@inria.fr>, Denis Merigoux
|
|
|
|
<denis.merigoux@inria.fr>
|
2022-01-18 20:51:02 +03:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
|
|
use this file except in compliance with the License. You may obtain a copy of
|
|
|
|
the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
License for the specific language governing permissions and limitations under
|
|
|
|
the License. *)
|
|
|
|
|
2022-11-21 12:46:17 +03:00
|
|
|
open Catala_utils
|
2022-08-12 23:42:39 +03:00
|
|
|
open Shared_ast
|
2022-01-18 20:51:02 +03:00
|
|
|
|
|
|
|
module type Backend = sig
|
2022-01-19 12:12:20 +03:00
|
|
|
val init_backend : unit -> unit
|
|
|
|
|
2022-01-18 20:51:02 +03:00
|
|
|
type backend_context
|
|
|
|
|
2022-11-16 23:59:48 +03:00
|
|
|
val make_context : decl_ctx -> backend_context
|
2022-01-19 12:12:20 +03:00
|
|
|
|
2022-01-18 20:51:02 +03:00
|
|
|
type vc_encoding
|
|
|
|
|
|
|
|
val print_encoding : vc_encoding -> string
|
|
|
|
|
|
|
|
type model
|
|
|
|
type solver_result = ProvenTrue | ProvenFalse of model option | Unknown
|
|
|
|
|
|
|
|
val solve_vc_encoding : backend_context -> vc_encoding -> solver_result
|
|
|
|
val print_model : backend_context -> model -> string
|
|
|
|
val is_model_empty : model -> bool
|
2022-01-19 11:47:08 +03:00
|
|
|
|
|
|
|
val translate_expr :
|
2022-08-25 20:46:13 +03:00
|
|
|
backend_context -> typed Dcalc.Ast.expr -> backend_context * vc_encoding
|
2022-11-09 00:09:35 +03:00
|
|
|
|
|
|
|
val encode_asserts :
|
|
|
|
backend_context -> typed Dcalc.Ast.expr -> backend_context
|
2022-01-18 20:51:02 +03:00
|
|
|
end
|
|
|
|
|
2022-01-19 12:17:19 +03:00
|
|
|
module type BackendIO = sig
|
|
|
|
val init_backend : unit -> unit
|
2022-01-19 11:47:08 +03:00
|
|
|
|
|
|
|
type backend_context
|
|
|
|
|
2022-11-16 23:59:48 +03:00
|
|
|
val make_context : decl_ctx -> backend_context
|
2022-01-19 12:17:19 +03:00
|
|
|
|
|
|
|
type vc_encoding
|
|
|
|
|
|
|
|
val translate_expr :
|
2022-08-25 20:46:13 +03:00
|
|
|
backend_context -> typed Dcalc.Ast.expr -> backend_context * vc_encoding
|
2022-01-19 12:17:19 +03:00
|
|
|
|
2022-11-09 00:09:35 +03:00
|
|
|
val encode_asserts :
|
|
|
|
backend_context -> typed Dcalc.Ast.expr -> backend_context
|
|
|
|
|
2022-01-19 11:47:08 +03:00
|
|
|
type model
|
|
|
|
|
|
|
|
type vc_encoding_result =
|
|
|
|
| Success of vc_encoding * backend_context
|
|
|
|
| Fail of string
|
|
|
|
|
|
|
|
val print_negative_result :
|
2022-07-12 16:57:50 +03:00
|
|
|
Conditions.verification_condition ->
|
2022-01-19 11:47:08 +03:00
|
|
|
backend_context ->
|
|
|
|
model option ->
|
|
|
|
string
|
|
|
|
|
|
|
|
val encode_and_check_vc :
|
2022-09-06 15:10:32 +03:00
|
|
|
decl_ctx -> Conditions.verification_condition * vc_encoding_result -> bool
|
2022-01-19 11:47:08 +03:00
|
|
|
end
|
|
|
|
|
2022-01-19 12:17:19 +03:00
|
|
|
module MakeBackendIO (B : Backend) = struct
|
|
|
|
let init_backend = B.init_backend
|
2022-01-19 11:47:08 +03:00
|
|
|
|
|
|
|
type backend_context = B.backend_context
|
|
|
|
|
2022-01-19 12:17:19 +03:00
|
|
|
let make_context = B.make_context
|
|
|
|
|
|
|
|
type vc_encoding = B.vc_encoding
|
|
|
|
|
|
|
|
let translate_expr = B.translate_expr
|
2022-11-09 00:09:35 +03:00
|
|
|
let encode_asserts = B.encode_asserts
|
2022-01-19 12:17:19 +03:00
|
|
|
|
2022-01-19 11:47:08 +03:00
|
|
|
type model = B.model
|
|
|
|
|
2022-01-18 20:51:02 +03:00
|
|
|
type vc_encoding_result =
|
|
|
|
| Success of B.vc_encoding * B.backend_context
|
|
|
|
| Fail of string
|
|
|
|
|
|
|
|
let print_negative_result
|
2022-07-12 16:57:50 +03:00
|
|
|
(vc : Conditions.verification_condition)
|
2022-01-18 20:51:02 +03:00
|
|
|
(ctx : B.backend_context)
|
|
|
|
(model : B.model option) : string =
|
|
|
|
let var_and_pos =
|
|
|
|
match vc.Conditions.vc_kind with
|
|
|
|
| Conditions.NoEmptyError ->
|
2023-06-07 19:10:50 +03:00
|
|
|
Format.asprintf
|
|
|
|
"@[<v>@{<yellow>[%a.%s]@} This variable might return an empty error:@,\
|
|
|
|
%a@]"
|
2023-07-12 12:48:46 +03:00
|
|
|
ScopeName.format vc.vc_scope
|
2023-06-07 19:10:50 +03:00
|
|
|
(Bindlib.name_of (Mark.remove vc.vc_variable))
|
|
|
|
Pos.format_loc_text (Mark.get vc.vc_variable)
|
2022-01-18 20:51:02 +03:00
|
|
|
| Conditions.NoOverlappingExceptions ->
|
|
|
|
Format.asprintf
|
2023-06-07 19:10:50 +03:00
|
|
|
"@[<v>@{<yellow>[%a.%s]@} At least two exceptions overlap for this \
|
|
|
|
variable:@,\
|
|
|
|
%a@]"
|
2023-07-12 12:48:46 +03:00
|
|
|
ScopeName.format vc.vc_scope
|
2023-06-07 19:10:50 +03:00
|
|
|
(Bindlib.name_of (Mark.remove vc.vc_variable))
|
|
|
|
Pos.format_loc_text (Mark.get vc.vc_variable)
|
2022-01-18 20:51:02 +03:00
|
|
|
in
|
|
|
|
let counterexample : string option =
|
2023-06-28 16:57:52 +03:00
|
|
|
if Globals.disable_counterexamples () then
|
2022-02-10 18:49:01 +03:00
|
|
|
Some "Counterexample generation is disabled so none was generated."
|
|
|
|
else
|
|
|
|
match model with
|
|
|
|
| None ->
|
2022-01-18 20:51:02 +03:00
|
|
|
Some
|
2022-02-10 18:49:01 +03:00
|
|
|
"The solver did not manage to generate a counterexample to explain \
|
|
|
|
the faulty behavior."
|
|
|
|
| Some model ->
|
|
|
|
if B.is_model_empty model then None
|
|
|
|
else
|
|
|
|
Some
|
|
|
|
(Format.asprintf
|
|
|
|
"The solver generated the following counterexample to explain \
|
|
|
|
the faulty behavior:\n\
|
|
|
|
%s"
|
|
|
|
(B.print_model ctx model))
|
2022-01-18 20:51:02 +03:00
|
|
|
in
|
|
|
|
var_and_pos
|
|
|
|
^
|
|
|
|
match counterexample with
|
|
|
|
| None -> ""
|
|
|
|
| Some counterexample -> "\n" ^ counterexample
|
2022-03-08 17:03:14 +03:00
|
|
|
|
2022-01-18 20:51:02 +03:00
|
|
|
let encode_and_check_vc
|
2023-05-02 17:33:23 +03:00
|
|
|
(_decl_ctx : decl_ctx)
|
2022-09-06 15:10:32 +03:00
|
|
|
(vc : Conditions.verification_condition * vc_encoding_result) : bool =
|
2022-01-18 20:51:02 +03:00
|
|
|
let vc, z3_vc = vc in
|
|
|
|
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.debug "@[<v>For this variable:@,%a@,@]" Pos.format_loc_text
|
2023-06-07 19:10:50 +03:00
|
|
|
(Expr.pos vc.Conditions.vc_guard);
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.debug
|
2023-06-07 19:10:50 +03:00
|
|
|
"@[<v>This verification condition was generated for @{<yellow>%s@}:@,\
|
|
|
|
%a@,\
|
|
|
|
with assertions:@,\
|
|
|
|
%a@]"
|
2022-03-08 15:04:27 +03:00
|
|
|
(match vc.vc_kind with
|
|
|
|
| Conditions.NoEmptyError ->
|
|
|
|
"the variable definition never to return an empty error"
|
|
|
|
| NoOverlappingExceptions -> "no two exceptions to ever overlap")
|
2023-05-02 17:33:23 +03:00
|
|
|
(Print.expr ()) vc.vc_guard (Print.expr ()) vc.vc_asserts;
|
2022-01-18 20:51:02 +03:00
|
|
|
|
|
|
|
match z3_vc with
|
|
|
|
| Success (encoding, backend_ctx) -> (
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.debug "@[<v>The translation to Z3 is the following:@,%s@]"
|
2022-03-08 15:04:27 +03:00
|
|
|
(B.print_encoding encoding);
|
2022-01-18 20:51:02 +03:00
|
|
|
match B.solve_vc_encoding backend_ctx encoding with
|
2022-09-06 15:10:32 +03:00
|
|
|
| ProvenTrue -> true
|
2022-03-08 15:04:27 +03:00
|
|
|
| ProvenFalse model ->
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.warning "%s" (print_negative_result vc backend_ctx model);
|
2022-09-06 15:10:32 +03:00
|
|
|
false
|
2022-01-18 20:51:02 +03:00
|
|
|
| Unknown -> failwith "The solver failed at proving or disproving the VC")
|
2022-03-15 20:02:08 +03:00
|
|
|
| Fail msg ->
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.warning
|
2023-06-07 19:10:50 +03:00
|
|
|
"@[<v>@{<yellow>[%a.%s]@} The translation to Z3 failed:@,%s@]"
|
2023-07-12 12:48:46 +03:00
|
|
|
ScopeName.format vc.vc_scope
|
2023-06-07 19:10:50 +03:00
|
|
|
(Bindlib.name_of (Mark.remove vc.vc_variable))
|
2022-09-06 15:10:32 +03:00
|
|
|
msg;
|
|
|
|
false
|
2022-01-18 20:51:02 +03:00
|
|
|
end
|