From c4820caec713995bc150a763cd150e36bcde9ede Mon Sep 17 00:00:00 2001 From: Andrei Paskevich <andrei@lri.fr> Date: Sat, 19 Sep 2015 15:34:37 +0200 Subject: [PATCH] Mlw: do not require "variant" for toplevel let-functions If we have a top-level total let-function definition and no variants are supplied, then we expect the definition to be terminating with respect to Decl.check_termination. --- src/mlw/expr.ml | 7 ++++++- src/mlw/pdecl.ml | 9 ++++++++- theories/list.why | 15 +++++++-------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/mlw/expr.ml b/src/mlw/expr.ml index f10ee20394..9e320044f3 100644 --- a/src/mlw/expr.ml +++ b/src/mlw/expr.ml @@ -964,7 +964,12 @@ let let_rec fdl = "All functions in a recursive definition must use the same \ well-founded order for the first component of the variant" in List.iter check_variant (List.tl fdl); - let start_eff = if varl1 = [] then + (* if we have a top-level total let-function definition and + no variants are supplied, then we expect the definition + to be terminating with respect to Decl.check_termination *) + let impure (_,d,_,k) = + (k <> RKfunc && k <> RKpred) || d.c_cty.cty_pre <> [] in + let start_eff = if varl1 = [] && List.exists impure fdl then eff_diverge eff_empty else eff_empty in (* create the first substitution *) let update sm (s,({c_cty = c} as d),varl,_) = diff --git a/src/mlw/pdecl.ml b/src/mlw/pdecl.ml index 67908f4ec1..f795cfb125 100644 --- a/src/mlw/pdecl.ml +++ b/src/mlw/pdecl.ml @@ -435,9 +435,16 @@ let create_let_decl ld = List.fold_right add_rd rdl ([],[],[]) | LDsym (s,c) -> add_ls Mrs.empty s c ([],[],[]) in + let fail_trusted_rec ls = + Loc.error ?loc:ls.ls_name.id_loc (Decl.NoTerminationProof ls) in + let is_trusted_rec = match ld with + | LDrec ({rec_sym = {rs_logic = RLls ls; rs_cty = c}; rec_varl = []}::_) + when not c.cty_effect.eff_oneway -> abst = [] || fail_trusted_rec ls + | _ -> false in let defn = if defn = [] then [] else let dl = List.map (fun (s,vl,t) -> make_ls_defn s vl t) defn in - try [create_logic_decl dl] with Decl.NoTerminationProof _ -> + try [create_logic_decl dl] with Decl.NoTerminationProof ls -> + if is_trusted_rec then fail_trusted_rec ls; let abst = List.map (fun (s,_) -> create_param_decl s) dl in let mk_ax ({ls_name = id} as s, vl, t) = let nm = id.id_string ^ "_def" in diff --git a/theories/list.why b/theories/list.why index 8df7107d72..a79c43d958 100644 --- a/theories/list.why +++ b/theories/list.why @@ -16,7 +16,7 @@ theory Length use import int.Int use import List - let rec function length (l: list 'a) : int variant {l} = + let rec function length (l: list 'a) : int = match l with | Nil -> 0 | Cons _ r -> 1 + length r @@ -65,7 +65,7 @@ theory Nth use import option.Option use import int.Int - let rec function nth (n: int) (l: list 'a) : option 'a variant {l} = + let rec function nth (n: int) (l: list 'a) : option 'a = match l with | Nil -> None | Cons x r -> if n = 0 then Some x else nth (n - 1) r @@ -163,7 +163,7 @@ theory Append use import List - let rec function (++) (l1 l2: list 'a) : list 'a variant {l1} = + let rec function (++) (l1 l2: list 'a) : list 'a = match l1 with | Nil -> l2 | Cons x1 r1 -> Cons x1 (r1 ++ l2) @@ -218,7 +218,7 @@ theory Reverse use import List use import Append - let rec function reverse (l: list 'a) : list 'a variant {l} = + let rec function reverse (l: list 'a) : list 'a = match l with | Nil -> Nil | Cons x r -> reverse r ++ Cons x Nil @@ -258,7 +258,7 @@ theory RevAppend use import List - let rec function rev_append (s t: list 'a) : list 'a variant {s} = + let rec function rev_append (s t: list 'a) : list 'a = match s with | Cons x r -> rev_append r (Cons x t) | Nil -> t @@ -295,7 +295,6 @@ theory Combine use import List let rec function combine (x: list 'a) (y: list 'b) : list ('a, 'b) - variant {x} = match x, y with | Cons x0 x, Cons y0 y -> Cons (x0, y0) (combine x y) | _ -> Nil @@ -496,7 +495,7 @@ theory Prefix use import List use import int.Int - let rec function prefix (n: int) (l: list 'a) : list 'a variant {l} = + let rec function prefix (n: int) (l: list 'a) : list 'a = if n <= 0 then Nil else match l with | Nil -> Nil @@ -510,7 +509,7 @@ theory Sum use import List use import int.Int - let rec function sum (l: list int) : int variant {l} = + let rec function sum (l: list int) : int = match l with | Nil -> 0 | Cons x r -> x + sum r -- GitLab