diff --git a/.ocamlformat b/.ocamlformat index b1bc4470bd72ad17da3b022db1369d0f7afa8e80..fe6b478e4b92fc68351704f501802748f670a884 100644 --- a/.ocamlformat +++ b/.ocamlformat @@ -3,3 +3,4 @@ parens-tuple=multi-line-only wrap-comments=true cases-exp-indent=2 break-cases=nested +break-fun-decl=wrap diff --git a/src/backends/C/c_backend_spec.ml b/src/backends/C/c_backend_spec.ml index 505a58b881c45b54d37f9dba53f6b7b3258de2a8..fe72e4c3752bb4b87a414ed39239c9ab972ae89a 100644 --- a/src/backends/C/c_backend_spec.ml +++ b/src/backends/C/c_backend_spec.ml @@ -8,8 +8,8 @@ (* version 2.1. *) (* *) (********************************************************************) - -open Utils.Format +open Utils +open Format open Lustre_types open Machine_code_types open C_backend_common @@ -299,23 +299,18 @@ let pp_reset_cleared pp_mem_in pp_mem_out fmt (name, mem_in, mem_out) = let pp_reset_cleared' = pp_reset_cleared pp_print_string pp_print_string -let pp_functional_update mems fmt mem = - let rec aux fmt mems = - match mems with +let pp_functional_update mems insts fmt mem = + let rec aux fmt = function | [] -> pp_print_string fmt mem - | x :: mems -> - fprintf fmt "{ @[<hov>%a@ \\with ._reg.%s = %s@] }" aux mems x x + | (x, is_mem) :: fields -> + fprintf fmt "{ @[<hov>%a@ \\with .%s%s = %s@] }" aux fields + (if is_mem then "_reg." else "") + x x in aux fmt - (* if Utils.ISet.is_empty mems then - * pp_print_string fmt mem - * else - * fprintf fmt "{ %s @[<hov>\\with %a@] }" - * mem - * (pp_print_list ~pp_sep:(fun fmt () -> fprintf fmt "@;<1 -6>\\with ") - * (fun fmt x -> fprintf fmt "._reg.%s = %s" x x)) *) - (Utils.ISet.elements mems) + (List.map (fun (x, _) -> x, false) (Utils.IMap.bindings insts) + @ List.map (fun x -> x, true) (Utils.ISet.elements mems)) module PrintSpec = struct type mode = @@ -365,12 +360,13 @@ module PrintSpec = struct fun ?output fmt e -> pp_expr ?output m mem_out fmt e in match p with - | Transition (f, inst, i, inputs, locals, outputs, r, mems) -> + | Transition (f, inst, i, inputs, locals, outputs, r, mems, insts) -> let pp_mem_in, pp_mem_out = match inst with | None -> ( pp_print_string, - if mem_update then pp_functional_update mems else pp_print_string ) + if mem_update then pp_functional_update mems insts + else pp_print_string ) | Some inst -> ( (fun fmt mem_in -> if r then pp_print_string fmt mem_in @@ -422,7 +418,7 @@ module PrintSpec = struct eprintf "Internal error: arrow not found"; raise Not_found - let pp_spec mode m fmt f = + let pp_spec mode m = let rec pp_spec mode fmt f = let mem_in, mem_in', indirect_r, mem_out, mem_out', indirect_l = let self = mk_self m in @@ -504,16 +500,7 @@ module PrintSpec = struct fmt ((f, mk_mem_reset m), (rc, tr)) in - match mode with - | TransitionFootprintMode -> - let mem_in = mk_mem_in m in - let mem_out = mk_mem_out m in - pp_forall - (pp_machine_decl ~ghost:true (pp_comma_list pp_print_string)) - (pp_spec mode) fmt - ((m.mname.node_id, [ mem_in; mem_out ]), f) - | _ -> - pp_spec mode fmt f + pp_spec mode end let pp_predicate pp_l pp_r fmt (l, r) = @@ -583,31 +570,50 @@ let pp_transition_footprint fmt t = t.tindex let pp_transition_footprint_lemma m fmt t = - let open Utils.ISet in let name = t.tname.node_id in + let mem_in = mk_mem_in m in + let mem_out = mk_mem_out m in let mems = - diff (of_list (List.map (fun v -> v.var_id) m.mmemory)) t.tfootprint + ISet.( + diff (of_list (List.map (fun v -> v.var_id) m.mmemory)) t.tmem_footprint) + in + let insts = + IMap.( + diff + (of_list (List.map (fun (x, (td, _)) -> x, node_name td) m.minstances)) + t.tinst_footprint) in let memories = List.map (fun v -> { v with var_type = { v.var_type with tid = -1 } }) - (List.filter (fun v -> not (mem v.var_id t.tfootprint)) m.mmemory) + (List.filter (fun v -> ISet.mem v.var_id mems) m.mmemory) + in + let mems_empty = ISet.is_empty mems in + let insts_empty = IMap.is_empty insts in + let instances = List.map (fun (i, f) -> f, i) (IMap.bindings insts) in + let tr ?mems ?insts () = + Spec_common.mk_transition ?mems ?insts ?i:t.tindex name + (vdecls_to_vals t.tinputs) (vdecls_to_vals t.tlocals) + (vdecls_to_vals t.toutputs) in - if not (is_empty mems) then + if not (mems_empty && insts_empty) then pp_acsl (pp_lemma pp_transition_footprint - (PrintSpec.pp_spec TransitionFootprintMode m)) + (pp_forall + (pp_machine_decl ~ghost:true (pp_comma_list pp_print_string)) + ((if insts_empty then fun pp fmt (_, x) -> pp fmt x + else pp_forall (pp_comma_list (pp_machine_decl' ~ghost:true))) + ((if mems_empty then fun pp fmt (_, x) -> pp fmt x + else pp_forall (pp_locals m)) + (PrintSpec.pp_spec TransitionFootprintMode m))))) fmt ( t, - Forall - ( memories @ t.tinputs @ t.tlocals @ t.toutputs, - Imply - ( Spec_common.mk_transition ?i:t.tindex name - (vdecls_to_vals t.tinputs) (vdecls_to_vals t.tlocals) - (vdecls_to_vals t.toutputs), - Spec_common.mk_transition ~mems ?i:t.tindex name - (vdecls_to_vals t.tinputs) (vdecls_to_vals t.tlocals) - (vdecls_to_vals t.toutputs) ) ) ) + ( (m.mname.node_id, [ mem_in; mem_out ]), + ( instances, + ( memories, + Forall + ( t.tinputs @ t.tlocals @ t.toutputs, + Imply (tr (), tr ~mems ~insts ()) ) ) ) ) ) let pp_transition_footprint_lemmas fmt m = pp_print_list ~pp_epilogue:pp_print_cut ~pp_open_box:pp_open_vbox0 diff --git a/src/machine_code.ml b/src/machine_code.ml index 44645a32bed90dfb7f8aa439dc76660be18e4ec6..cf324c94324ed58f21966f27b0a5411cd07b0400 100644 --- a/src/machine_code.ml +++ b/src/machine_code.ml @@ -137,7 +137,6 @@ let translate_guard env expr = let rec translate_act env (y, expr) = let translate_act = translate_act env in let translate_guard = translate_guard env in - (* let translate_ident = translate_ident env in *) let translate_expr = translate_expr env in let lustre_eq = Corelang.mkeq Location.dummy_loc ([ y.var_id ], expr) in match expr.expr_desc with @@ -193,6 +192,8 @@ type machine_ctx = { * var_decl list (* outputs *) * ISet.t (* memory footprint *) + * ident IMap.t + (* memory instances footprint *) * mc_formula_t) (* formula *) list; @@ -250,6 +251,7 @@ let translate_eq env ctx nd inputs locals outputs i eq = locals_i, outputs_i, ctx.m, + IMap.map (fun (td, _) -> node_name td) ctx.j, Exists ( Lustre_live.existential_vars id i eq (locals @ outputs), And @@ -303,13 +305,9 @@ let translate_eq env ctx nd inputs locals outputs i eq = (MStep ([ var_x ], inst, [ c1; c2 ])) (mk_memory_pack ~inst (node_name td)) (mk_transition ~inst (node_name td) [] [] [ vdecl_to_val var_x ]) - ctx + { ctx with j = IMap.add inst (td, []) ctx.j } in - { - ctx with - si = mkinstr (MSetReset inst) :: ctx.si; - j = IMap.add inst (td, []) ctx.j; - } + { ctx with si = mkinstr (MSetReset inst) :: ctx.si } | [ x ], Expr_pre e when env.is_local x -> let var_x = env.get_var x in let e = translate_expr e in @@ -354,7 +352,11 @@ let translate_eq env ctx nd inputs locals outputs i eq = (MStep (var_p, inst, vl)) (mk_memory_pack ~inst (node_name node_f)) (mk_transition ?r ~inst (node_name node_f) vl [] (vdecls_to_vals var_p)) - ctx + { + ctx with + j = IMap.add inst call_f ctx.j; + s = (if Stateless.check_node node_f then [] else reset_inst) @ ctx.s; + } in (*Clocks.new_var true in Clock_calculus.unify_imported_clock (Some call_ck) eq.eq_rhs.expr_clock eq.eq_rhs.expr_loc; Format.eprintf "call %a: %a: @@ -365,8 +367,6 @@ let translate_eq env ctx nd inputs locals outputs i eq = si = (if Stateless.check_node node_f then ctx.si else mkinstr (MSetReset inst) :: ctx.si); - j = IMap.add inst call_f ctx.j; - s = (if Stateless.check_node node_f then [] else reset_inst) @ ctx.s; } | [ x ], _ -> let var_x = env.get_var x in @@ -476,7 +476,8 @@ let transition_0 nd = tlocals = []; toutputs = []; tformula = True; - tfootprint = ISet.empty; + tmem_footprint = ISet.empty; + tinst_footprint = IMap.empty; } let transition_toplevel nd i = @@ -495,7 +496,8 @@ let transition_toplevel nd i = tformula = (if fst (get_stateless_status_node nd) then tr else ExistsMem (nd.node_id, Predicate (ResetCleared nd.node_id), tr)); - tfootprint = ISet.empty; + tmem_footprint = ISet.empty; + tinst_footprint = IMap.empty; } let translate_decl nd sch = @@ -562,7 +564,7 @@ let translate_decl nd sch = transition_0 nd :: List.mapi - (fun i (tinputs, tlocals, toutputs, tfootprint, f) -> + (fun i (tinputs, tlocals, toutputs, tmem_footprint, tinst_footprint, f) -> { tname = nd; tindex = Some (i + 1); @@ -570,7 +572,8 @@ let translate_decl nd sch = tlocals; toutputs; tformula = red f; - tfootprint; + tmem_footprint; + tinst_footprint; }) (List.rev ctx.t) @ [ transition_toplevel nd (List.length ctx.t) ] diff --git a/src/machine_code_common.ml b/src/machine_code_common.ml index 3248efb87811035e6162a86ff9193b142508a398..af44a8ec969ca118fe20bc97a9a8a3b95678c72c 100644 --- a/src/machine_code_common.ml +++ b/src/machine_code_common.ml @@ -58,7 +58,7 @@ module PrintSpec = struct fun fmt e -> pp_expr m fmt e in match p with - | Transition (f, inst, i, inputs, locals, outputs, _r, _mems) -> + | Transition (f, inst, i, inputs, locals, outputs, _r, _mems, _insts) -> fprintf fmt "Transition_%a<%a>%a%a" pp_print_string f (pp_print_option ~none:(fun fmt () -> pp_print_string fmt "SELF") @@ -321,30 +321,17 @@ let id_to_tag id = mk_val (Cst (Const_tag id)) (Type_predef.type_const typ) let mk_conditional ?lustre_eq c t e = - mkinstr ?lustre_eq - (* (Ternary (Val c, - * And (List.map get_instr_spec t), - * And (List.map get_instr_spec e))) *) - (MBranch (c, [ tag_true, t; tag_false, e ])) - -let mk_branch ?lustre_eq c br = - mkinstr ?lustre_eq - (* (And (List.map (fun (l, instrs) -> - * Imply (Equal (Val c, Tag l), And (List.map get_instr_spec instrs))) - * br)) *) - (MBranch (c, br)) + mkinstr ?lustre_eq (MBranch (c, [ tag_true, t; tag_false, e ])) + +let mk_branch ?lustre_eq c br = mkinstr ?lustre_eq (MBranch (c, br)) let mk_branch' ?lustre_eq v = mk_branch ?lustre_eq (vdecl_to_val v) -let mk_assign ?lustre_eq x v = - mkinstr ?lustre_eq (* (Equal (Var x, Val v)) *) (MLocalAssign (x, v)) +let mk_assign ?lustre_eq x v = mkinstr ?lustre_eq (MLocalAssign (x, v)) let arrow_machine = let state = "_first" in - let var_state = - dummy_var_decl state Type_predef.type_bool - (* (Types.new_ty Types.Tbool) *) - in + let var_state = dummy_var_decl state Type_predef.type_bool in let var_input1 = List.nth Arrow.arrow_desc.node_inputs 0 in let var_input2 = List.nth Arrow.arrow_desc.node_inputs 1 in let var_output = List.nth Arrow.arrow_desc.node_outputs 0 in diff --git a/src/spec_common.ml b/src/spec_common.ml index 399cb31b71dfe88004b5a8803ba32c555dc97b25..6f3c9373bb641f05fedaea2dcbfd9298bbc3e6da 100644 --- a/src/spec_common.ml +++ b/src/spec_common.ml @@ -1,4 +1,5 @@ open Spec_types +open Utils (* a small reduction engine *) let is_true = function True -> true | _ -> false @@ -73,20 +74,13 @@ let rec red : type a. a formula_t -> a formula_t = function f (* smart constructors *) -(* let mk_condition x l = - * if l = tag_true then Ternary (Val x, True, False) - * else if l = tag_false then Ternary (Val x, False, True) - * else Equal (Val x, Tag l) *) let vals vs = List.map (fun v -> Val v) vs let mk_pred_call pred = Predicate pred -(* let mk_clocked_on id = - * mk_pred_call (Clocked_on id) *) - -let mk_transition ?(mems = Utils.ISet.empty) ?r ?i ?inst id inputs locals - outputs = +let mk_transition ?(mems = ISet.empty) ?(insts = IMap.empty) ?r ?i ?inst id + inputs locals outputs = let tr = mk_pred_call (Transition @@ -97,7 +91,8 @@ let mk_transition ?(mems = Utils.ISet.empty) ?r ?i ?inst id inputs locals vals locals, vals outputs, (match r with Some _ -> true | None -> false), - mems )) + mems, + insts )) in match r, inst with | Some r, Some inst -> @@ -113,7 +108,14 @@ let mk_state_assign_tr x v = Equal (Memory (StateVar x), Val v) let mk_conditional_tr v t f = Ternary (Val v, t, f) -let mk_branch_tr x hl = - And (List.map (fun (t, spec) -> Imply (Equal (Var x, Tag t), spec)) hl) +let mk_branch_tr x = + let open Lustre_types in + function + | [ (h1, spec1); (h2, spec2) ] when h1 = tag_true && h2 = tag_false -> + Ternary (Var x, spec1, spec2) + | [ (h1, spec1); (h2, spec2) ] when h1 = tag_false && h2 = tag_true -> + Ternary (Var x, spec2, spec1) + | hl -> + And (List.map (fun (t, spec) -> Imply (Equal (Var x, Tag t), spec)) hl) let mk_assign_tr x v = Equal (Var x, Val v) diff --git a/src/spec_types.ml b/src/spec_types.ml index e8ed01ad6ce243b4c013a3d392dce4840621bf11..c1201c3a138b98171a008ae892c320d86ebddac8 100644 --- a/src/spec_types.ml +++ b/src/spec_types.ml @@ -39,6 +39,8 @@ type 'a predicate_t = (* outputs *) * bool (* reset *) * Utils.ISet.t (* memory footprint *) + * ident Utils.IMap.t + (* memory instances footprint *) -> 'a predicate_t | Reset of ident * ident * 'a | MemoryPack of ident * ident option * int option @@ -80,5 +82,6 @@ type 'a transition_t = { tlocals : var_decl list; toutputs : var_decl list; tformula : 'a formula_t; - tfootprint : Utils.ISet.t; + tmem_footprint : Utils.ISet.t; + tinst_footprint : ident Utils.IMap.t; } diff --git a/src/utils/env.ml b/src/utils/env.ml index d4e03231350f39e3ecd65a780dc4e94d73a68bec..8a6c7bcae80dbea64cf0606e86d10e7c333f35af 100644 --- a/src/utils/env.ml +++ b/src/utils/env.ml @@ -35,8 +35,7 @@ let overwrite x y = x y let pp_env pp_fun fmt env = - let lid, lty = list_of_imap env in - let l' = List.combine lid lty in + let l' = IMap.bindings env in let pp_fun fmt (id, value) = Format.fprintf fmt "%s |-> %a" id pp_fun value in Format.fprintf fmt "{ @[<v 2>%a@] }" (fprintf_list ~sep:"@," pp_fun) l' diff --git a/src/utils/utils.ml b/src/utils/utils.ml index ef930561f58d3945ec615a61cc27ef2cdbfa51a9..5283e7aa05db1c5e15aadc156a45fcf9146a6150 100644 --- a/src/utils/utils.ml +++ b/src/utils/utils.ml @@ -41,17 +41,17 @@ end module IMap = struct include Map.Make (IdentModule) - let union_l m1 m2 = + let diff m1 m2 = merge (fun _ o1 o2 -> match o1, o2 with - | None, None -> - None - | Some _, _ -> - o1 - | _, Some _ -> - o2) + | Some v1, Some v2 -> + if v1 = v2 then None else o1 + | _ -> + o1) m1 m2 + + let of_list l = List.fold_left (fun m (x, v) -> add x v m) empty l end module ISet = Set.Make (IdentModule) @@ -123,10 +123,6 @@ let rec filter_upto p n l = | t :: q -> if p t then t :: filter_upto p (n - 1) q else filter_upto p n q -(* Warning: bad complexity *) -let list_of_imap imap = - IMap.fold (fun i v (il, vl) -> i :: il, v :: vl) imap ([], []) - (** [gcd a b] returns the greatest common divisor of [a] and [b]. *) let rec gcd a b = if b = 0 then a else gcd b (a mod b)