From dd787602f5af1fcdca870f8a8f4ad762d0e2cf9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fumex?= <clement.fumex@inria.fr>
Date: Wed, 2 Mar 2016 15:11:17 +0100
Subject: [PATCH] load proof first attempt

---
 src/session/session_itp.ml  | 447 ++++++++++++++++++++++--------------
 src/session/session_itp.mli |  30 ++-
 2 files changed, 297 insertions(+), 180 deletions(-)

diff --git a/src/session/session_itp.ml b/src/session/session_itp.ml
index 4affa3893c..a33bd1d325 100644
--- a/src/session/session_itp.ml
+++ b/src/session/session_itp.ml
@@ -3,21 +3,27 @@ open Stdlib
 module Hprover = Whyconf.Hprover
 
 let debug = Debug.register_info_flag "session_itp"
-  ~desc:"Pring@ debugging@ messages@ about@ Why3@ session@ \
-         creation,@ reading@ and@ writing."
+    ~desc:"Pring@ debugging@ messages@ about@ Why3@ session@ \
+           creation,@ reading@ and@ writing."
 
 type transID = int
 type proofNodeID = int
 
-type proof_parent = Trans of transID | Theory of Theory.theory
+type theory = {
+  theory_name     : Ident.ident;
+  theory_checksum : Termcode.checksum option;
+  theory_goals    : proofNodeID list;
+}
+
+type proof_parent = Trans of transID | Theory of theory
 
 type proof_attempt = {
   prover         : Whyconf.prover;
   timelimit      : int;
   memlimit       : int;
   stepslimit     : int;
-  proof_state    : Call_provers.prover_result option;  (* None means that the call was not done
-                                                       or never returned *)
+  proof_state    : Call_provers.prover_result option;
+  (* None means that the call was not done or never returned *)
   proof_obsolete : bool;
   proof_script   : string option;  (* non empty for external ITP *)
 }
@@ -49,20 +55,14 @@ type transformation_node = {
   transf_parent   : proofNodeID;
 }
 
-type theory = {
-  theory_name     : Ident.ident;
-  theory_checksum : Termcode.checksum option;
-  theory_goals    : proofNodeID list;
-}
-
 type file = {
   file_name     : string;
   file_format   : string option;
   file_theories : theory list;
 }
 
-type session = {
-  task_table                    : proof_node Hint.t;
+ type session = {
+  proofNode_table                    : proof_node Hint.t;
   mutable next_proofNodeID      : int;
   trans_table                   : transformation_node Hint.t;
   mutable next_transID          : int;
@@ -70,7 +70,7 @@ type session = {
   mutable session_shape_version : int;
   session_prover_ids            : int Hprover.t;
   session_file_name             : string;
- }
+}
 
 let gen_transID (s : session) =
   let id = s.next_transID in
@@ -82,12 +82,23 @@ let gen_proofNodeID (s : session) =
   s.next_proofNodeID <- id + 1;
   id
 
+exception BadID
+let get_proofNode (s : session) (id : proofNodeID) =
+  try
+    Hint.find s.proofNode_table id
+  with Not_found -> raise BadID
+
+let get_transfNode (s : session) (id : transID) =
+  try
+    Hint.find s.trans_table id
+  with Not_found -> raise BadID
+
 let empty_session ?shape_version (file : string) =
   let shape_version = match shape_version with
     | Some v -> v
     | None -> Termcode.current_shape_version
   in
-  { task_table = Hint.create 97;
+  { proofNode_table = Hint.create 97;
     next_proofNodeID = 0;
     trans_table = Hint.create 97;
     next_transID = 0;
@@ -97,35 +108,52 @@ let empty_session ?shape_version (file : string) =
     session_file_name = file;
   }
 
-exception BadID
-
 let graft_proof_attempt (s : session) (id : proofNodeID) (pa : proof_attempt) =
-  try
-    let pn = Hint.find s.task_table id in
-    let node = { proofa_parent = id; proofa_attempt = pa } in
-    Hprover.replace pn.proofn_attempts pa.prover node
-  with Not_found -> raise BadID
+  let pn = get_proofNode s id in
+  let node = { proofa_parent = id; proofa_attempt = pa } in
+  Hprover.replace pn.proofn_attempts pa.prover node
+
+let remove_proof_attempt (s : session) (id : proofNodeID)
+    (prover : Whyconf.prover) =
+  let pn = get_proofNode s id in
+  Hprover.remove pn.proofn_attempts prover
+
+(* [mk_proof_node s t p id] register in the session [s] a proof node
+   of proofNodeID [id] of parent [p] of task [t] *)
+let mk_proof_node (s : session) (t : Task.task) (parent : proof_parent)
+    (node_id : proofNodeID) =
+  let pn = { proofn_task = t; proofn_parent = parent;
+             proofn_attempts = Hprover.create 7;
+             proofn_transformations = []} in
+  Hint.add s.proofNode_table node_id pn
 
-let mk_proof_node (s : session) (tid : int) (t : Task.task) =
+let mk_transf_proof_node (s : session) (tid : int) (t : Task.task) =
   let id = gen_proofNodeID s in
-  let pn = { proofn_task = t; proofn_parent = Trans tid;
-             proofn_attempts = Hprover.create 3;
-             proofn_transformations = []} in
-  Hint.add s.task_table id pn;
+  mk_proof_node s t (Trans tid) id;
   id
 
-let graft_transf  (s : session) (id : proofNodeID) (name : string) (l : trans_arg list) (tl : Task.task list) =
-  try
-    let pn = Hint.find s.task_table id in
-    let tid = gen_transID s in
-    let sub_tasks = List.map (mk_proof_node s tid) tl in
-    let tn = { transf_name = name;
-               transf_args = l;
-               transf_subtasks = sub_tasks;
-               transf_parent = id; } in
-    Hint.replace s.trans_table tid tn;
-    pn.proofn_transformations <- tid::pn.proofn_transformations
-  with Not_found -> raise BadID
+let mk_transf_node (s : session) (id : proofNodeID) (node_id : transID)
+    (name : string) (args : trans_arg list) (pnl : proofNodeID list) =
+  let pn = get_proofNode s id in
+  let tn = { transf_name = name;
+             transf_args = args;
+             transf_subtasks = pnl;
+             transf_parent = id; } in
+  Hint.add s.trans_table node_id tn;
+  pn.proofn_transformations <- node_id::pn.proofn_transformations
+
+let graft_transf  (s : session) (id : proofNodeID) (name : string)
+    (args : trans_arg list) (tl : Task.task list) =
+  let tid = gen_transID s in
+  let sub_tasks = List.map (mk_transf_proof_node s tid) tl in
+  mk_transf_node s id tid name args sub_tasks
+
+let remove_transformation (s : session) (id : transID) =
+  let nt = get_transfNode s id in
+  Hint.remove s.trans_table id;
+  let pn = get_proofNode s nt.transf_parent in
+  let trans_up = List.filter (fun tid -> tid != id) pn.proofn_transformations in
+  pn.proofn_transformations <- trans_up;
 
 (************************)
 (* saving state on disk *)
@@ -150,9 +178,9 @@ exception SessionFileError of string
 let bool_attribute field r def =
   try
     match List.assoc field r.Xml.attributes with
-      | "true" -> true
-      | "false" -> false
-      | _ -> assert false
+    | "true" -> true
+    | "false" -> false
+    | _ -> assert false
   with Not_found -> def
 
 let int_attribute_def field r def =
@@ -189,46 +217,46 @@ let string_attribute field r =
 
 let load_result r =
   match r.Xml.name with
-    | "result" ->
-        let status = string_attribute "status" r in
-        let answer =
-          match status with
-            | "valid" -> Call_provers.Valid
-            | "invalid" -> Call_provers.Invalid
-            | "unknown" -> Call_provers.Unknown ("", None)
-            | "timeout" -> Call_provers.Timeout
-            | "outofmemory" -> Call_provers.OutOfMemory
-            | "failure" -> Call_provers.Failure ""
-            | "highfailure" -> Call_provers.HighFailure
-            | "steplimitexceeded" -> Call_provers.StepLimitExceeded
-            | "stepslimitexceeded" -> Call_provers.StepLimitExceeded
-            | s ->
-                Warning.emit
-                  "[Warning] Session.load_result: unexpected status '%s'@." s;
-                Call_provers.HighFailure
-        in
-        let time =
-          try float_of_string (List.assoc "time" r.Xml.attributes)
-          with Not_found -> 0.0
-        in
-        let steps =
-          try int_of_string (List.assoc "steps" r.Xml.attributes)
-          with Not_found -> -1
-        in
-        Some {
-          Call_provers.pr_answer = answer;
-          Call_provers.pr_time = time;
-          Call_provers.pr_output = "";
-          Call_provers.pr_status = Unix.WEXITED 0;
-	  Call_provers.pr_steps = steps;
-	  Call_provers.pr_model = Model_parser.default_model;
-        }
-    | "undone" -> None
-    | "unedited" -> None
-    | s ->
-        Warning.emit "[Warning] Session.load_result: unexpected element '%s'@."
-          s;
-        None
+  | "result" ->
+    let status = string_attribute "status" r in
+    let answer =
+      match status with
+      | "valid" -> Call_provers.Valid
+      | "invalid" -> Call_provers.Invalid
+      | "unknown" -> Call_provers.Unknown ("", None)
+      | "timeout" -> Call_provers.Timeout
+      | "outofmemory" -> Call_provers.OutOfMemory
+      | "failure" -> Call_provers.Failure ""
+      | "highfailure" -> Call_provers.HighFailure
+      | "steplimitexceeded" -> Call_provers.StepLimitExceeded
+      | "stepslimitexceeded" -> Call_provers.StepLimitExceeded
+      | s ->
+        Warning.emit
+          "[Warning] Session.load_result: unexpected status '%s'@." s;
+        Call_provers.HighFailure
+    in
+    let time =
+      try float_of_string (List.assoc "time" r.Xml.attributes)
+      with Not_found -> 0.0
+    in
+    let steps =
+      try int_of_string (List.assoc "steps" r.Xml.attributes)
+      with Not_found -> -1
+    in
+    Some {
+      Call_provers.pr_answer = answer;
+      Call_provers.pr_time = time;
+      Call_provers.pr_output = "";
+      Call_provers.pr_status = Unix.WEXITED 0;
+      Call_provers.pr_steps = steps;
+      Call_provers.pr_model = Model_parser.default_model;
+    }
+  | "undone" -> None
+  | "unedited" -> None
+  | s ->
+    Warning.emit "[Warning] Session.load_result: unexpected element '%s'@."
+      s;
+    None
 
 let load_option attr g =
   try Some (List.assoc attr g.Xml.attributes)
@@ -237,13 +265,13 @@ let load_option attr g =
 let load_ident elt =
   let name = string_attribute "name" elt in
   let label = List.fold_left
-    (fun acc label ->
-      match label with
-        | {Xml.name = "label"} ->
-            let lab = string_attribute "name" label in
-            Ident.Slab.add (Ident.create_label lab) acc
-        | _ -> acc
-    ) Ident.Slab.empty elt.Xml.elements in
+      (fun acc label ->
+         match label with
+         | {Xml.name = "label"} ->
+           let lab = string_attribute "name" label in
+           Ident.Slab.add (Ident.create_label lab) acc
+         | _ -> acc
+      ) Ident.Slab.empty elt.Xml.elements in
   let preid =
     try
       let load_exn attr g = List.assoc attr g.Xml.attributes in
@@ -263,96 +291,179 @@ type load_ctxt = {
 
 let read_file_session_and_shapes dir xml_filename =
   try
-  let compressed_shape_filename =
-    Filename.concat dir compressed_shape_filename
-  in
-  if Sys.file_exists compressed_shape_filename then
-(*    if Compress.compression_supported then
-     Session.ReadShapesCompress.read_xml_and_shapes
-       xml_filename compressed_shape_filename
-      else *)
+    let compressed_shape_filename =
+      Filename.concat dir compressed_shape_filename
+    in
+    if Sys.file_exists compressed_shape_filename then
+      (*    if Compress.compression_supported then
+            Session.ReadShapesCompress.read_xml_and_shapes
+             xml_filename compressed_shape_filename
+            else *)
       begin
         Warning.emit "[Warning] could not read goal shapes because \
-                                Why3 was not compiled with compress support@.";
+                      Why3 was not compiled with compress support@.";
         Xml.from_file xml_filename, false
       end
-  else
-    let shape_filename = Filename.concat dir shape_filename in
-(*    if Sys.file_exists shape_filename then
-      ReadShapesNoCompress.read_xml_and_shapes xml_filename shape_filename
-      else*)
+    else
+      let shape_filename = Filename.concat dir shape_filename in
+      (*    if Sys.file_exists shape_filename then
+            ReadShapesNoCompress.read_xml_and_shapes xml_filename shape_filename
+            else*)
       begin
         Warning.emit "[Warning] could not find goal shapes file@.";
         Xml.from_file xml_filename, false
       end
-with e ->
-  Warning.emit "[Warning] failed to read goal shapes: %s@."
-    (Printexc.to_string e);
-  Xml.from_file xml_filename, false
-
-let load_file session old_provers f = old_provers
-(*  match f.Xml.name with
-    | "file" ->
-       let ctxt = { old_provers = old_provers ; keygen = keygen } in
-        let fn = string_attribute "name" f in
-        let fmt = load_option "format" f in
-        let expanded = bool_attribute "expanded" f false in
-        let mf = raw_add_file ~keygen:ctxt.keygen ~expanded session fn fmt in
-        mf.file_theories <-
-          List.rev
-          (List.fold_left
-             (load_theory ctxt mf) [] f.Xml.elements);
-        mf.file_verified <- file_verified mf;
-        old_provers
-    | "prover" ->
-      (* The id is just for the session file *)
-        let id = string_attribute "id" f in
-        begin
-          try
-            let id = int_of_string id in
-            let name = string_attribute "name" f in
-            let version = string_attribute "version" f in
-            let altern = string_attribute_def "alternative" f "" in
-            let timelimit = int_attribute_def "timelimit" f 5 in
-	    let steplimit = int_attribute_def "steplimit" f 1 in
-            let memlimit = int_attribute_def "memlimit" f 1000 in
-            let p = {C.prover_name = name;
-                     prover_version = version;
-                     prover_altern = altern} in
-            Mint.add id (p,timelimit,steplimit,memlimit) old_provers
-          with Failure _ ->
-            Warning.emit "[Warning] Session.load_file: unexpected non-numeric prover id '%s'@." id;
-            old_provers
-        end
+  with e ->
+    Warning.emit "[Warning] failed to read goal shapes: %s@."
+      (Printexc.to_string e);
+    Xml.from_file xml_filename, false
+
+(* [load_goal s op p g id] loads the goal of parent [p] from the xml
+   [g] of nodeID [id] into the session [s] *)
+let rec load_goal session old_provers parent g id =
+  match g.Xml.name with
+  | "goal" -> mk_proof_node session None parent id;
+    List.iter (load_proof_or_transf session old_provers id) g.Xml.elements;
+  | "label" -> ()
+  | s ->
+    Warning.emit "[Warning] Session.load_goal: unexpected element '%s'@." s
+
+(* [load_proof_or_transf s op id a] load either a proof attempt or a
+   transformation of parent id [pid] from the xml [a] into the session
+   [s] *)
+and load_proof_or_transf session old_provers pid a =
+  match a.Xml.name with
+    | "proof" ->
+      begin
+        let prover = string_attribute "prover" a in
+        try
+          let prover = int_of_string prover in
+          let (p,timelimit,steplimit,memlimit) = Mint.find prover old_provers in
+          let res = match a.Xml.elements with
+            | [r] -> load_result r
+            | [] -> None
+            | _ ->
+              Warning.emit "[Error] Too many result elements@.";
+              raise (LoadError (a,"too many result elements"))
+          in
+          let edit = load_option "edited" a in
+          let edit = match edit with None | Some "" -> None | _ -> edit in
+          let obsolete = bool_attribute "obsolete" a false in
+          let timelimit = int_attribute_def "timelimit" a timelimit in
+	  let steplimit = int_attribute_def "steplimit" a steplimit in
+          let memlimit = int_attribute_def "memlimit" a memlimit in
+          let pa = { prover = p;
+                     timelimit = timelimit;
+                     memlimit = memlimit;
+                     stepslimit = steplimit;
+                     proof_state = res;
+                     proof_obsolete = obsolete;
+                     proof_script = edit;
+                   } in
+          graft_proof_attempt session pid pa
+        with Failure _ | Not_found ->
+          Warning.emit "[Error] prover id not listed in header '%s'@." prover;
+          raise (LoadError (a,"prover not listing in header"))
+      end
+    | "transf" ->
+        let trname = string_attribute "name" a in
+        let tid = gen_transID session in
+        let subtasks = List.fold_left (fun goals th -> match th.Xml.name with
+        | "goal" -> (gen_proofNodeID session) :: goals
+        | _ -> goals) [] a.Xml.elements in
+        mk_transf_node session pid tid trname [] subtasks;
+        List.iter2
+          (load_goal session old_provers (Trans tid))
+          a.Xml.elements subtasks;
+    | "metas" -> ()
+    | "label" -> ()
     | s ->
-        Warning.emit "[Warning] Session.load_file: unexpected element '%s'@." s;
+        Warning.emit
+          "[Warning] Session.load_proof_or_transf: unexpected element '%s'@."
+          s
+
+let load_theory session old_provers acc th =
+  match th.Xml.name with
+  | "theory" ->
+    let thname = load_ident th in
+    let csum = string_attribute_opt "sum" th in
+    let checksum = Opt.map Termcode.checksum_of_string csum in
+    let goals = List.fold_left (fun goals th -> match th.Xml.name with
+        | "goal" -> (gen_proofNodeID session) :: goals
+        | _ -> goals) [] th.Xml.elements in
+    let mth = { theory_name = thname;
+                theory_checksum = checksum;
+                theory_goals = goals; } in
+    List.iter2
+      (load_goal session old_provers (Theory mth))
+      th.Xml.elements goals;
+    mth::acc
+  | s ->
+    Warning.emit "[Warning] Session.load_theory: unexpected element '%s'@."
+      s;
+    acc
+
+let load_file session old_provers f = (* old_provers *)
+  match f.Xml.name with
+  | "file" ->
+    let fn = string_attribute "name" f in
+    let fmt = load_option "format" f in
+    let ft = List.rev
+        (List.fold_left
+           (load_theory session old_provers) [] f.Xml.elements) in
+    let mf = { file_name = fn;
+               file_format = fmt;
+               file_theories = ft; } in
+    Hstr.add session.session_files fn mf;
+    old_provers
+  | "prover" ->
+    (* The id is just for the session file *)
+    let id = string_attribute "id" f in
+    begin
+      try
+        let id = int_of_string id in
+        let name = string_attribute "name" f in
+        let version = string_attribute "version" f in
+        let altern = string_attribute_def "alternative" f "" in
+        let timelimit = int_attribute_def "timelimit" f 5 in
+        let steplimit = int_attribute_def "steplimit" f 1 in
+        let memlimit = int_attribute_def "memlimit" f 1000 in
+        let p = {Whyconf.prover_name = name;
+                 prover_version = version;
+                 prover_altern = altern} in
+        Mint.add id (p,timelimit,steplimit,memlimit) old_provers
+      with Failure _ ->
+        Warning.emit "[Warning] Session.load_file: unexpected non-numeric prover id '%s'@." id;
         old_provers
-        *)
+    end
+  | s ->
+    Warning.emit "[Warning] Session.load_file: unexpected element '%s'@." s;
+    old_provers
 
 let build_session (s : session) xml =
   match xml.Xml.name with
-    | "why3session" ->
-      let shape_version = int_attribute_def "shape_version" xml 1 in
-      s.session_shape_version <- shape_version;
-      Debug.dprintf debug "[Info] load_session: shape version is %d@\n" shape_version;
-      (* just to keep the old_provers somewhere *)
-      let old_provers =
-        List.fold_left (load_file s) Mint.empty xml.Xml.elements
-      in
-      Mint.iter
-        (fun id (p,_,_,_) ->
-          Debug.dprintf debug "prover %d: %a@." id Whyconf.print_prover p;
-          Hprover.replace s.session_prover_ids p id)
-        old_provers;
-      Debug.dprintf debug "[Info] load_session: done@\n"
-    | s ->
-        Warning.emit "[Warning] Session.load_session: unexpected element '%s'@."
-          s
+  | "why3session" ->
+    let shape_version = int_attribute_def "shape_version" xml 1 in
+    s.session_shape_version <- shape_version;
+    Debug.dprintf debug "[Info] load_session: shape version is %d@\n" shape_version;
+    (* just to keep the old_provers somewhere *)
+    let old_provers =
+      List.fold_left (load_file s) Mint.empty xml.Xml.elements
+    in
+    Mint.iter
+      (fun id (p,_,_,_) ->
+         Debug.dprintf debug "prover %d: %a@." id Whyconf.print_prover p;
+         Hprover.replace s.session_prover_ids p id)
+      old_provers;
+    Debug.dprintf debug "[Info] load_session: done@\n"
+  | s ->
+    Warning.emit "[Warning] Session.load_session: unexpected element '%s'@."
+      s
 
 let load_session (file : string) =
   let session = empty_session file in
   let use_shapes =
-  (* If the xml is present we read it, otherwise we consider it empty *)
+    (* If the xml is present we read it, otherwise we consider it empty *)
     if Sys.file_exists file then
       try
         Termcode.reset_dict ();
@@ -364,12 +475,12 @@ let load_session (file : string) =
         with Sys_error msg ->
           failwith ("Open session: sys error " ^ msg)
       with
-        | Sys_error msg ->
+      | Sys_error msg ->
         (* xml does not exist yet *)
-          raise (SessionFileError msg)
-        | Xml.Parse_error s ->
-          Warning.emit "XML database corrupted, ignored (%s)@." s;
-          raise (SessionFileError "XML corrupted")
-  else false
+        raise (SessionFileError msg)
+      | Xml.Parse_error s ->
+        Warning.emit "XML database corrupted, ignored (%s)@." s;
+        raise (SessionFileError "XML corrupted")
+    else false
   in
   session, use_shapes
diff --git a/src/session/session_itp.mli b/src/session/session_itp.mli
index c8fe7daa0c..9ada5af38a 100644
--- a/src/session/session_itp.mli
+++ b/src/session/session_itp.mli
@@ -7,9 +7,11 @@ type trans_arg
 
 (* (\** New Proof sessions ("Refectoire") *\) *)
 
-(* note: la fonction register des transformations doit permettre de declarer les types des arguments
+(* note: la fonction register des transformations doit permettre de
+   declarer les types des arguments
 
-  type trans_arg_type = TTint | TTstring | TTterm | TTty | TTtysymbol | TTlsymbol | TTprsymbol
+   type trans_arg_type = TTint | TTstring | TTterm | TTty | TTtysymbol
+   | TTlsymbol | TTprsymbol
 
 *)
 
@@ -19,32 +21,36 @@ val graft_proof_attempt : session -> proofNodeID -> proof_attempt -> unit
 (** [graft_proof_attempt s id pa] adds the proof attempt [pa] as a
     child of the task [id] of the session [s]. *)
 
-val graft_transf : session -> proofNodeID -> string -> trans_arg list -> Task.task list -> unit
+val graft_transf : session -> proofNodeID -> string -> trans_arg list ->
+  Task.task list -> unit
 (** [graft_transf s id name l tl] adds the transformation [name] as a
-    child of the task [id] of the session [s]. [l] is the list of argument
-    of the transformation; [tl] is the resulting list of tasks *)
+    child of the task [id] of the session [s]. [l] is the list of
+    argument of the transformation; [tl] is the resulting list of
+    tasks *)
 
 val remove_proof_attempt : session -> proofNodeID -> Whyconf.prover -> unit
 (** [remove_proof_attempt s id pr] removes the proof attempt from the
     prover [pr] from the proof node [id] of the session [s] *)
 
-val remove_transformation : session -> proofNodeID -> transID -> unit
-(** [remove_transformation s pid tid] removes the transformation [tid] from
-    the proof node [pid] of the session [s] *)
+val remove_transformation : session -> transID -> unit
+(** [remove_transformation s id] removes the transformation [id]
+    from the session [s] *)
 
-val save_session : string -> session -> unit
+(* val save_session : string -> session -> unit *)
 (** [save_session f s] Save the session [s] in file [f] *)
 
-val load_session : string -> session
+val load_session : string -> session * bool
 (** [load_session f] load a session from a file [f]; all the tasks are
     initialised to None *)
 (*
 
-  couche au-dessus: "scheduler" cad modifications asynchrones de la session
+  couche au-dessus: "scheduler" cad modifications asynchrones de la
+  session
 
    - gere une file de travaux de modifications a faire
-   - recupere les resultats de travaux , et les applique s'ils sont encore valides
 
+   - recupere les resultats de travaux , et les applique s'ils sont
+     encore valides
 *)
 (*
 type theory =
-- 
GitLab