From fc95fe10d14e372454791fc8c7d158d36c4c572b Mon Sep 17 00:00:00 2001 From: Virgile Prevosto <virgile.prevosto@m4x.org> Date: Thu, 25 Nov 2021 18:10:00 +0100 Subject: [PATCH] [logic] Fixes lv_type field of variables whose value is a function Fixes #1093 --- src/kernel_services/ast_queries/filecheck.ml | 7 ++++--- .../ast_queries/logic_const.ml | 5 +++++ .../ast_queries/logic_const.mli | 7 +++++++ .../ast_queries/logic_typing.ml | 19 ++++++------------- tests/spec/local_lambda.i | 9 +++++++++ tests/spec/oracle/local_lambda.res.oracle | 13 +++++++++++++ 6 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 tests/spec/local_lambda.i create mode 100644 tests/spec/oracle/local_lambda.res.oracle diff --git a/src/kernel_services/ast_queries/filecheck.ml b/src/kernel_services/ast_queries/filecheck.ml index 397fad32079..18d9d1cab1c 100644 --- a/src/kernel_services/ast_queries/filecheck.ml +++ b/src/kernel_services/ast_queries/filecheck.ml @@ -815,16 +815,17 @@ module Base_checker = struct | None -> check_abort "Trying to use predicate %a as a term" Printer.pp_logic_var lvi - | Some typ -> + | Some rt -> + let ft = Logic_const.make_arrow_type li.l_profile rt in if not - (Logic_utils.is_instance_of li.l_tparams t.term_type typ) + (Logic_utils.is_instance_of li.l_tparams t.term_type ft) then check_abort "%a is declared with type %a. It cannot be used as \ a term of type %a" Printer.pp_logic_var lvi - Printer.pp_logic_type typ + Printer.pp_logic_type ft Printer.pp_logic_type t.term_type) with Not_found -> check_abort diff --git a/src/kernel_services/ast_queries/logic_const.ml b/src/kernel_services/ast_queries/logic_const.ml index 28623b64f5e..b7b632bb888 100644 --- a/src/kernel_services/ast_queries/logic_const.ml +++ b/src/kernel_services/ast_queries/logic_const.ml @@ -226,6 +226,11 @@ let transform_element f t = set_conversion (plain_or_set f t) t let is_plain_type ty = not (is_set_type ty) +let make_arrow_type args rt = + match args with + | [] -> rt + | _ -> Larrow(List.map (fun x -> x.lv_type) args, rt) + let rec is_boolean_type = function | Ltype ({ lt_name = s }, []) when s = Utf8_logic.boolean -> true | Ltype (tdef,_) as ty when is_unrollable_ltdef tdef -> diff --git a/src/kernel_services/ast_queries/logic_const.mli b/src/kernel_services/ast_queries/logic_const.mli index db448d2e6de..a18c91e6b7e 100644 --- a/src/kernel_services/ast_queries/logic_const.mli +++ b/src/kernel_services/ast_queries/logic_const.mli @@ -283,6 +283,13 @@ val transform_element: (logic_type -> logic_type) -> logic_type -> logic_type @modify 18.0-Argon expands the logic type definition if necessary. *) val is_plain_type: logic_type -> bool +(** [make_arrow_type args rt] returns a [rt] if [args] is empty or the + corresponding [Larrow] type. + + @since Frama-C+dev +*) +val make_arrow_type: logic_var list -> logic_type -> logic_type + (** @return true if the argument is the boolean type. @modify 18.0-Argon expands the logic type definition if necessary. *) val is_boolean_type: logic_type -> bool diff --git a/src/kernel_services/ast_queries/logic_typing.ml b/src/kernel_services/ast_queries/logic_typing.ml index d7c956b7eb7..8950bee942e 100644 --- a/src/kernel_services/ast_queries/logic_typing.ml +++ b/src/kernel_services/ast_queries/logic_typing.ml @@ -2039,7 +2039,7 @@ struct | _,typ -> { term with term_node = Tlambda(quants, term); - term_type = Larrow(List.map (fun x -> x.lv_type) quants,typ) } + term_type = make_arrow_type quants typ } in let rec aux known_vars kont term = match term.term_node with @@ -2948,7 +2948,7 @@ struct | _ -> [],tdef in var.l_type <- Some tdef.term_type; - var.l_var_info.lv_type <- tdef.term_type; + var.l_var_info.lv_type <- make_arrow_type args tdef.term_type; var.l_profile <- args; var.l_body <- LBterm tdef; let env = Lenv.add_logic_info ident var env in @@ -3455,10 +3455,8 @@ struct in let var = Cil_const.make_logic_info_local x in var.l_profile <- args; - var.l_var_info.lv_type <- - (match typ with - None -> Ctype (Cil.voidType) - | Some t -> t); + let rt = Option.value typ ~default:(Ctype Cil.voidType) in + var.l_var_info.lv_type <- make_arrow_type args rt; var.l_type <- typ; var.l_body <- tdef; let env = Lenv.add_logic_info x var env in @@ -4003,13 +4001,8 @@ struct - Polymorphism is not reflected on the lvar level. - However, such lvar should rarely if at all be seen under a Tvar. *) - (match p,t with - _,None -> () - | [], Some t -> - info.l_var_info.lv_type <- t - | _,Some t -> - let typ = Larrow (List.map (fun x -> x.lv_type) p,t) in - info.l_var_info.lv_type <- typ); + let rt = Option.value t ~default:(Ctype Cil.voidType) in + info.l_var_info.lv_type <- make_arrow_type p rt; info.l_tparams <- poly; info.l_profile <- p; info.l_type <- t; diff --git a/tests/spec/local_lambda.i b/tests/spec/local_lambda.i new file mode 100644 index 00000000000..336c1721354 --- /dev/null +++ b/tests/spec/local_lambda.i @@ -0,0 +1,9 @@ +/*@ logic integer id(integer x) = x; */ + +/*@ lemma test1: 55 == \sum(1,10,id); */ + +/*@ lemma test2: 5 == \let x = (\lambda integer y; y); x(5); */ + +/*@ lemma test3: 55 == \sum(1,10,\lambda integer y; y); */ + +/*@ lemma test4: 55 == \let x = (\lambda integer y; y); \sum(1,10,x); */ diff --git a/tests/spec/oracle/local_lambda.res.oracle b/tests/spec/oracle/local_lambda.res.oracle new file mode 100644 index 00000000000..d77e1eb63c2 --- /dev/null +++ b/tests/spec/oracle/local_lambda.res.oracle @@ -0,0 +1,13 @@ +[kernel] Parsing tests/spec/local_lambda.i (no preprocessing) +/* Generated by Frama-C */ +/*@ logic ℤ id(ℤ x) = x; + */ +/*@ lemma test1: 55 ≡ \sum(1, 10, id); + */ +/*@ lemma test2: 5 ≡ (\let x = \lambda ℤ y; y; x(5)); + */ +/*@ lemma test3: 55 ≡ \sum(1, 10, \lambda ℤ y; y); + */ +/*@ lemma test4: 55 ≡ (\let x = \lambda ℤ y; y; \sum(1, 10, x)); + */ + -- GitLab