Commit 42e2dbe1 authored by Andrei Paskevich's avatar Andrei Paskevich

format-specific environment

parent 0c23f68f
......@@ -374,7 +374,7 @@ install_local: bin/why3
########
PGM_FILES = pgm_ttree pgm_types pgm_pretty \
pgm_module pgm_wp pgm_env pgm_typing pgm_ocaml pgm_main
pgm_module pgm_wp pgm_typing pgm_ocaml pgm_main
PGMMODULES = $(addprefix src/programs/, $(PGM_FILES))
......
......@@ -70,12 +70,11 @@ let scanf s =
(** the main function *)
let read_channel env path filename cin =
(** Find the int theory and the needed operation *)
let th_int = Env.find_theory env ["int"] "Int" in
let th_int = Env.find_theory (Env.env_of_library env) ["int"] "Int" in
let leq = ns_find_ls th_int.th_export ["infix <"] in
let plus_symbol = Theory.ns_find_ls th_int.Theory.th_export ["infix +"] in
let mult_symbol = Theory.ns_find_ls th_int.Theory.th_export ["infix *"] in
let zero = t_int_const "0" in
(** create a contraint : polynome <= constant *)
......@@ -128,6 +127,6 @@ let read_channel env path filename cin =
(** Read all the file *)
let th_uc = Sysutil.fold_channel fold th_uc cin in
(** Return the map with the theory *)
Mstr.singleton "EqLin" (close_theory th_uc)
(), Mstr.singleton "EqLin" (close_theory th_uc)
let () = Env.register_format "EquLin" ["equlin"] read_channel
let library_of_env = Env.register_format "EquLin" ["equlin"] read_channel
......@@ -252,10 +252,10 @@ and comment_line = parse
let lb = Lexing.from_channel c in
Loc.set_file file lb;
let ast = with_location (tptp_file token) lb in
Tptp_typing.typecheck env path ast
(), Tptp_typing.typecheck env path ast
(* let () = Env.register_format "tptp" ["p";"ax"] read_channel *)
let () = Env.register_format "tff1" ["p";"ax"] read_channel
(* let library_of_env = Env.register_format "tptp" ["p";"ax"] read_channel *)
let library_of_env = Env.register_format "tff1" ["p";"ax"] read_channel
}
(*
......
......@@ -17,6 +17,6 @@
(* *)
(**************************************************************************)
val typecheck : Why3.Env.env -> Why3.Env.pathname ->
val typecheck : unit Why3.Env.library -> Why3.Env.pathname ->
Tptp_ast.tptp_file -> Why3.Theory.theory Why3.Util.Mstr.t
......@@ -26,20 +26,19 @@ open Theory
type fformat = string (* format name *)
type filename = string (* file name *)
type extension = string (* file extension *)
type pathname = string list (* path in an environment *)
type pathname = string list (* library path *)
exception KnownFormat of fformat
exception UnknownFormat of fformat
exception UnknownExtension of extension
exception UnspecifiedFormat
exception ChannelNotFound of pathname
exception LibFileNotFound of pathname
exception TheoryNotFound of pathname * string
exception AmbiguousPath of filename * filename
type env = {
env_path : filename list;
env_memo : (pathname, theory Mstr.t) Hashtbl.t;
env_tag : Hashweak.tag;
}
......@@ -47,27 +46,30 @@ let env_tag env = env.env_tag
module Wenv = Hashweak.Make(struct type t = env let tag = env_tag end)
(** Input formats *)
(** Environment construction and utilisation *)
type read_channel =
env -> pathname -> filename -> in_channel -> theory Mstr.t
let create_env = let c = ref (-1) in fun lp -> {
env_path = lp;
env_tag = (incr c; Hashweak.create_tag !c)
}
let read_channel_table = Hashtbl.create 17 (* format name -> read_channel *)
let extensions_table = Hashtbl.create 17 (* suffix -> format name *)
let get_loadpath env = env.env_path
let register_format name exts rc =
if Hashtbl.mem read_channel_table name then raise (KnownFormat name);
Hashtbl.add read_channel_table name (rc,exts);
List.iter (fun s -> Hashtbl.replace extensions_table ("." ^ s) name) exts
let read_format_table = Hashtbl.create 17 (* format name -> read_format *)
let extensions_table = Hashtbl.create 17 (* suffix -> format name *)
let lookup_format name =
try Hashtbl.find read_channel_table name
try Hashtbl.find read_format_table name
with Not_found -> raise (UnknownFormat name)
let list_formats () =
let add n (_,_,l) acc = (n,l)::acc in
Hashtbl.fold add read_format_table []
let get_extension file =
let s = try Filename.chop_extension file
with Invalid_argument _ -> raise UnspecifiedFormat in
let n = String.length s in
let n = String.length s + 1 in
String.sub file n (String.length file - n)
let get_format file =
......@@ -75,15 +77,12 @@ let get_format file =
try Hashtbl.find extensions_table ext
with Not_found -> raise (UnknownExtension ext)
let real_read_channel ?format env path file ic =
let read_channel ?format env file ic =
let name = match format with
| Some name -> name
| None -> get_format file in
let rc,_ = lookup_format name in
rc env path file ic
let read_channel ?format env file ic =
real_read_channel ?format env [] file ic
let rc,_,_ = lookup_format name in
rc env file ic
let read_file ?format env file =
let ic = open_in file in
......@@ -93,69 +92,78 @@ let read_file ?format env file =
mth
with e -> close_in ic; raise e
let list_formats () =
let add n (_,l) acc = (n,l)::acc in
Hashtbl.fold add read_channel_table []
let read_theory ~format env path th =
let _,rl,_ = lookup_format format in
rl env path th
let find_theory = read_theory ~format:"why"
(** Environment construction and utilisation *)
(** Navigation in the library *)
let create_env = let c = ref (-1) in fun lp -> {
env_path = lp;
env_memo = Hashtbl.create 17;
env_tag = (incr c; Hashweak.create_tag !c)
}
let create_env_of_loadpath lp =
Format.eprintf "WARNING: Env.create_env_of_loadpath is deprecated
and will be removed in future versions of Why3.
Replace it with Env.create_env.@.";
create_env lp
exception InvalidQualifier of string
let get_loadpath env = env.env_path
let check_qualifier s =
if (s = Filename.parent_dir_name ||
s = Filename.current_dir_name ||
Filename.basename s <> s)
then raise (InvalidQualifier s)
(* looks for file [file] of format [name] in loadpath [lp] *)
let locate_file name lp path =
let locate_lib_file env path exts =
List.iter check_qualifier path;
let file = List.fold_left Filename.concat "" path in
let _,sl = lookup_format name in
let add_sf sf = file ^ "." ^ sf in
let fl = if sl = [] then [file] else List.map add_sf sl in
let add_ext ext = file ^ "." ^ ext in
let fl = if exts = [] then [file] else List.map add_ext exts in
let add_dir dir = List.map (Filename.concat dir) fl in
let fl = List.concat (List.map add_dir lp) in
let fl = List.concat (List.map add_dir env.env_path) in
match List.filter Sys.file_exists fl with
| [] -> raise (ChannelNotFound path)
| [] -> raise (LibFileNotFound path)
| [file] -> file
| file1 :: file2 :: _ -> raise (AmbiguousPath (file1, file2))
exception InvalidQualifier of string
(** Input formats *)
let check_qualifier s =
if (s = Filename.parent_dir_name ||
s = Filename.current_dir_name ||
Filename.basename s <> s)
then raise (InvalidQualifier s)
exception CircularDependency of pathname
type 'a contents = 'a * theory Mstr.t
let find_channel env f sl =
List.iter check_qualifier sl;
let file = locate_file f env.env_path sl in
file, open_in file
type 'a library = {
lib_env : env;
lib_read : 'a read_format;
lib_exts : extension list;
lib_memo : (pathname, 'a contents option) Hashtbl.t;
}
and 'a read_format =
'a library -> pathname -> filename -> in_channel -> 'a contents
let mk_library read exts env = {
lib_env = env;
lib_read = read;
lib_exts = exts;
lib_memo = Hashtbl.create 17;
}
let env_of_library lib = lib.lib_env
let find_library env sl =
let file, ic = find_channel env "why" sl in
let read_lib_file lib path =
let file = locate_lib_file lib.lib_env path lib.lib_exts in
let ic = open_in file in
try
Hashtbl.replace env.env_memo sl Mstr.empty;
let mth = real_read_channel ~format:"why" env sl file ic in
Hashtbl.replace env.env_memo sl mth;
Hashtbl.replace lib.lib_memo path None;
let res = lib.lib_read lib path file ic in
Hashtbl.replace lib.lib_memo path (Some res);
close_in ic;
mth
res
with e ->
Hashtbl.remove env.env_memo sl;
Hashtbl.remove lib.lib_memo path;
close_in ic;
raise e
let find_library env sl =
try Hashtbl.find env.env_memo sl
with Not_found -> find_library env sl
let read_lib_file lib path =
try match Hashtbl.find lib.lib_memo path with
| Some res -> res
| None -> raise (CircularDependency path)
with Not_found -> read_lib_file lib path
let get_builtin s =
if s = builtin_theory.th_name.id_string then builtin_theory else
......@@ -165,22 +173,40 @@ let get_builtin s =
| Some n -> tuple_theory n
| None -> raise (TheoryNotFound ([],s))
let find_theory env sl s =
if sl = [] then get_builtin s else
let mth = find_library env sl in
try Mstr.find s mth with Not_found ->
raise (TheoryNotFound (sl,s))
let read_lib_theory lib path th =
if path = [] then get_builtin th else
let _,mth = read_lib_file lib path in
try Mstr.find th mth with Not_found ->
raise (TheoryNotFound (path,th))
let read_lib_file lib path = fst (read_lib_file lib path)
let register_format name exts read =
if Hashtbl.mem read_format_table name then raise (KnownFormat name);
let getlib = Wenv.memoize 5 (mk_library read exts) in
let rc env file ic = snd (read (getlib env) [] file ic) in
let rl env path th = read_lib_theory (getlib env) path th in
Hashtbl.add read_format_table name (rc,rl,exts);
List.iter (fun s -> Hashtbl.replace extensions_table s name) exts;
getlib
let locate_lib_file env format path =
let _,_,exts = lookup_format format in
locate_lib_file env path exts
(* Exception reporting *)
let print_path fmt sl =
Pp.print_list (Pp.constant_string ".") Format.pp_print_string fmt sl
let () = Exn_printer.register
begin fun fmt exn -> match exn with
| ChannelNotFound sl ->
Format.fprintf fmt "Library not found: %a"
(Pp.print_list (Pp.constant_string ".") Format.pp_print_string) sl
| CircularDependency sl ->
Format.fprintf fmt "Circular dependency in %a" print_path sl
| LibFileNotFound sl ->
Format.fprintf fmt "Library file not found: %a" print_path sl
| TheoryNotFound (sl,s) ->
Format.fprintf fmt "Theory not found: %a.%s"
(Pp.print_list (Pp.constant_string ".") Format.pp_print_string) sl s
Format.fprintf fmt "Theory not found: %a.%s" print_path sl s
| KnownFormat s ->
Format.fprintf fmt "Format %s is already registered" s
| UnknownFormat s ->
......
......@@ -17,53 +17,44 @@
(* *)
(**************************************************************************)
(** Library environment *)
type env
val env_tag : env -> Hashweak.tag
module Wenv : Hashweak.S with type key = env
open Util
open Theory
(** Local type aliases and exceptions *)
type fformat = string (* format name *)
type filename = string (* file name *)
type extension = string (* file extension *)
type pathname = string list (* path in an environment *)
type pathname = string list (* library path *)
exception KnownFormat of fformat
exception UnknownFormat of fformat
exception UnknownExtension of extension
exception UnspecifiedFormat
exception ChannelNotFound of pathname
exception LibFileNotFound of pathname
exception TheoryNotFound of pathname * string
(** Input formats *)
(** Library environment *)
open Theory
type env
val env_tag : env -> Hashweak.tag
type read_channel =
env -> pathname -> filename -> in_channel -> theory Util.Mstr.t
(** a function of type [read_channel] parses a channel using
its own syntax. The string argument indicates the origin of
the stream (e.g. file name) to be used in error messages. *)
module Wenv : Hashweak.S with type key = env
val register_format : fformat -> extension list -> read_channel -> unit
(** [register_format name extensions fn] registers a new format
called [name], for files with extensions in the string list
[extensions] (separating dot not included);
[fn] is the function to perform parsing.
val create_env : filename list -> env
(** creates an environment from a "loadpath", a list of directories
containing loadable Why3/WhyML/etc files *)
@raise KnownFormat [name] if the format is already registered *)
val get_loadpath : env -> filename list
(** returns the loadpath of a given environment *)
val read_channel :
?format:fformat -> env -> filename -> in_channel -> theory Util.Mstr.t
?format:fformat -> env -> filename -> in_channel -> theory Mstr.t
(** [read_channel ?format env path file ch] returns the theories in [ch].
When given, [format] enforces the format, otherwise we choose
the format according to [file]'s extension. Nothing ensures
that [ch] corresponds to the contents of [f].
that [ch] corresponds to the contents of [file].
@raise UnknownFormat [format] if the format is not registered
@raise UnknownExtension [s] if the extension [s] is not known
......@@ -71,35 +62,79 @@ val read_channel :
@raise UnspecifiedFormat if format is not given and [file]
has no extension *)
val read_file : ?format:fformat -> env -> filename -> theory Util.Mstr.t
val read_file : ?format:fformat -> env -> filename -> theory Mstr.t
(** [read_file ?format env file] returns the theories in [file].
When given, [format] enforces the format, otherwise we choose
the format according to [file]'s extension. *)
val read_theory : format:fformat -> env -> pathname -> string -> theory
(** [read_theory ~format env path th] returns the theory [path.th]
from the library. The parameter [format] speicifies the format
of the library file to look for.
@raise UnknownFormat [format] if the format is not registered
@raise LibFileNotFound [path] if the library file was not found
@raise TheoryNotFound if the theory was not found in the file *)
val find_theory : env -> pathname -> string -> theory
(** the same as [read_theory ~format:"why"]
This function is left for compatibility purposes and may be
removed in future versions of Why3. *)
(** Input formats *)
type 'a library
(** part of the environment restricted to a particular format *)
type 'a read_format =
'a library -> pathname -> filename -> in_channel -> 'a * theory Mstr.t
(** [(fn : 'a read_format) lib path file ch] parses the channel [ch]
and returns the format-specific contents of type ['a] and a set of
logical theories. References to the library files of the same format
are resolved via [lib]. If the parsed file is itself a part of
the library, the argument [path] contains the fully qualified
library name of the file, which can be put in the identifiers.
The string argument [file] indicates the origin of the stream
(e.g. file name) to be used in error messages. *)
val register_format :
fformat -> extension list -> 'a read_format -> (env -> 'a library)
(** [register_format fname exts read] registers a new format [fname]
for files with extensions from the string list [exts] (without
the separating dot); [read] is the function to perform parsing.
Returns a function that maps an environment to a format-specific
library inside it.
@raise KnownFormat [name] if the format is already registered *)
val env_of_library : 'a library -> env
(** [env_of_library lib] returns the environment of [lib] *)
val list_formats : unit -> (fformat * extension list) list
(** [list_formats ()] returns the list of registered formats *)
(** Environment construction and utilisation *)
val read_lib_file : 'a library -> pathname -> 'a
(** [read_lib_file lib path] retrieves the contents of a library file
val create_env : filename list -> env
(** creates an environment from a "loadpath", a list of directories
containing loadable Why3/WhyML/etc files *)
@raise LibFileNotFound [path] if the library file was not found *)
val create_env_of_loadpath : filename list -> env
(** the same as [create_env], will be removed in some future version *)
val read_lib_theory : 'a library -> pathname -> string -> theory
(** [read_lib_theory lib path th] returns the theory [path.th]
from the library. This is the same as [read_theory] above,
but the format is determined by [lib] and not by the extra
[format] parameter.
val get_loadpath : env -> filename list
(** returns the loadpath of a given environment *)
@raise LibFileNotFound [path] if the library file was not found
@raise TheoryNotFound if the theory was not found in the file *)
val find_channel : env -> fformat -> pathname -> filename * in_channel
(** finds an input channel in a given environment, knowing its format
and its name (presented as a list of strings); a filename is also
returned, to be used in logs or error messages.
val locate_lib_file : env -> fformat -> pathname -> filename
(** [locate_lib_file env format path] finds a library file in a given
environment, knowing its format and its library path
@raise ChannelNotFound [sl] if the channel [sl] was not found
@raise UnknownFormat [f] if the format is not registered *)
This is a low-level function that allows to accees a library file
without parsing it. Do not use it without a good reason to do.
val find_theory : env -> pathname -> string -> theory
(** a special case of [find_channel] that returns a particular theory,
using the format ["why"]
@raise LibFileNotFound [path] if the library file was not found
@raise UnknownFormat [format] if the format is not registered *)
@raise TheoryNotFound if the theory was not found in a channel *)
......@@ -174,7 +174,8 @@ let load_driver = let driver_tag = ref (-1) in fun env file ->
let add_theory { thr_name = (loc,q); thr_rules = trl } =
let f,id = let l = List.rev q in List.rev (List.tl l),List.hd l in
let th =
try Env.find_theory env f id with e -> raise (Loc.Located (loc,e))
try Env.read_theory ~format:"why" env f id
with e -> raise (Loc.Located (loc,e))
in
qualid := q;
List.iter (add_local th) trl
......
......@@ -394,18 +394,13 @@ let output_theory drv fname _tname th task dir =
Driver.print_task ?old drv (formatter_of_out_channel cout) task;
close_out cout
let do_task env drv fname tname (th : Theory.theory) (task : Task.task) =
let do_task drv fname tname (th : Theory.theory) (task : Task.task) =
match !opt_output, !opt_command with
| Some dir, _ when !opt_realize ->
output_theory drv fname tname th task dir
| None, _ when !opt_realize ->
(* FIXME: we should be able to realize other formats *)
let file,ich = Env.find_channel env "why" th.th_path in
let dir = try Filename.chop_extension file with _ ->
eprintf "File %s does not have an extension.@." file;
exit 1 in
close_in ich;
output_theory drv fname tname th task dir
eprintf "Output directory (-o) is required.@.";
exit 1
| Some dir, Some command when !opt_bisect ->
let test task =
let call = Driver.prove_task_prepared
......@@ -443,7 +438,7 @@ let do_tasks env drv fname tname th task =
List.rev_append (Trans.apply tr task) acc) [] tasks)
in
let tasks = List.fold_left apply [task] trans in
List.iter (do_task env drv fname tname th) tasks
List.iter (do_task drv fname tname th) tasks
let do_theory env drv fname tname th glist =
if !opt_print_theory then
......@@ -478,7 +473,8 @@ let do_theory env drv fname tname th glist =
end
let do_global_theory env drv (tname,p,t,glist) =
let th = try Env.find_theory env p t with Env.TheoryNotFound _ ->
let format = Util.default_option "why" !opt_parser in
let th = try Env.read_theory ~format env p t with Env.TheoryNotFound _ ->
eprintf "Theory '%s' not found.@." tname;
exit 1
in
......@@ -541,7 +537,7 @@ let () =
let drv = Util.option_map (load_driver env) !opt_driver in
Queue.iter (do_input env drv) opt_queue;
if !opt_token_count then
Format.printf "Total: %d annot/%d programs, ratio = %.3f@."
Format.printf "Total: %d annot/%d programs, ratio = %.3f@."
!total_annot_tokens !total_program_tokens
((float !total_annot_tokens) /. (float !total_program_tokens))
with e when not (Debug.test_flag Debug.stack_trace) ->
......
......@@ -19,12 +19,14 @@
(** parsing entry points *)
val library_of_env : Env.env -> unit Env.library
val parse_logic_file :
Env.env -> string list -> Lexing.lexbuf -> Theory.theory Util.Mstr.t
val parse_program_file : Lexing.lexbuf -> Ptree.program_file
val token_counter : Lexing.lexbuf -> int * int
val token_counter : Lexing.lexbuf -> int * int
(** other functions to be re-used in other lexers/parsers *)
......
......@@ -329,15 +329,16 @@ and string = parse
then loop in_annot (a+1) p
else loop in_annot a (p+1)
in
loop false 0 0
loop false 0 0
let read_channel env path file c =
let lb = Lexing.from_channel c in
Loc.set_file file lb;
parse_logic_file env path lb
(), parse_logic_file env path lb
let () = Env.register_format "why" ["why"] read_channel
let library_of_env = Env.register_format "why" ["why"] read_channel
let parse_logic_file env = parse_logic_file (library_of_env env)
}
(*
......
......@@ -258,7 +258,7 @@ end
/* Entry points */
%type <Env.env -> string list -> unit> pre_logic_file
%type <unit Env.library -> string list -> unit> pre_logic_file
%start pre_logic_file
%type <Theory.theory Util.Mstr.t> logic_file
%start logic_file
......
......@@ -1081,10 +1081,10 @@ let find_theory env lenv q id = match q with
| [] ->
(* local theory *)
begin try Mstr.find id lenv
with Not_found -> find_theory env [] id end
with Not_found -> read_lib_theory env [] id end
| _ :: _ ->
(* theory in file f *)
find_theory env q id
read_lib_theory env q id
let rec clone_ns loc sl ns2 ns1 s =
let clash id = error ~loc (Clash id.id_string) in
......
......@@ -29,7 +29,8 @@ val debug_type_only : Debug.flag
(** incremental parsing *)
val add_decl : Env.env -> theory Mstr.t -> theory_uc -> Ptree.decl -> theory_uc
val add_decl :
unit Env.library -> theory Mstr.t -> theory_uc -> Ptree.decl -> theory_uc
val close_namespace :
Loc.position -> bool -> Ptree.ident option -> theory_uc -> theory_uc
......
(**************************************************************************)
(* *)
(* Copyright (C) 2010-2011 *)
(* François Bobot *)
(* Jean-Christophe Filliâtre *)
(* Claude Marché *)
(* Andrei Paskevich *)
(* *)
(* This software is free software; you can redistribute it and/or *)
(* modify it under the terms of the GNU Library General Public *)
(* License version 2.1, with the special exception on linking *)
(* described in file LICENSE. *)
(* *)
(* This software is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)
(* *)
(**************************************************************************)
open Why3
open Util
open Theory
open Pgm_module
type module_file = Theory.theory Mstr.t * Pgm_module.t Mstr.t
type t = {
env : Env.env;
retrieve : retrieve_module;
memo : (string list, module_file) Hashtbl.t;
}
and retrieve_module = t -> string list -> string -> in_channel -> module_file
let get_env penv = penv.env
let create env retrieve = {
env = env;
retrieve = retrieve;
memo = Hashtbl.create 17;
}
exception ModuleNotFound of string list * string
let find_library penv sl =
try
Hashtbl.find penv.memo sl
with Not_found ->
Hashtbl.add penv.memo sl (Mstr.empty, Mstr.empty);
let file, c = Env.find_channel penv.env "whyml" sl in
let r = penv.retrieve penv sl file c in
close_in c;
Hashtbl.replace penv.memo sl r;
r
let find_module penv sl s =
try Mstr.find s (snd (find_library penv sl))
with Not_found -> raise (ModuleNotFound (sl, s))
(**************************************************************************)
(* *)
(* Copyright (C) 2010-2011 *)
(* François Bobot *)
(* Jean-Christophe Filliâtre *)
(* Claude Marché *)
(* Andrei Paskevich *)
(* *)
(* This software is free software; you can redistribute it and/or *)
(* modify it under the terms of the GNU Library General Public *)
(* License version 2.1, with the special exception on linking *)
(* described in file LICENSE. *)
(* *)
(* This software is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)
(* *)
(**************************************************************************)
open Why3
open Theory
open Pgm_module
type t
val get_env : t -> Env.env
type module_file = Theory.theory Util.Mstr.t * Pgm_module.t Util.Mstr.t
type retrieve_module = t -> string list -> string -> in_channel -> module_file
val create : Env.env -> retrieve_module -> t
exception ModuleNotFound of string list * string
val find_module : t -> string list -> string -> Pgm_module.t
(** [find_module e p n] finds the module named [p.n] in environment [e]
@raise ModuleNotFound if module not present in env [e] *)
......@@ -39,6 +39,7 @@ let () = Exn_printer.register (fun fmt e -> match e with
let add_theory env path lenv m =
let id = m.pth_name in
let loc = id.id_loc in
let env = Lexer.library_of_env (Env.env_of_library env) in
let th = Theory.create_theory ~path (Denv.create_user_id id) in
let rec add_decl th = function
| Dlogic d ->
......@@ -52,27 +53,26 @@ let add_theory env path lenv m =
let th = List.fold_left add_decl th m.pth_decl in
close_theory loc lenv th