From 0007b802d0904f48660e1e00f0cecdcb7a176564 Mon Sep 17 00:00:00 2001 From: Francois Bobot <bobot@lri.fr> Date: Thu, 11 Mar 2010 17:09:40 +0000 Subject: [PATCH] ajout des options --all-goals --goals-of Test --goal Test.G --output dir (-d),... --- Makefile.in | 9 ++- lib/drivers/alt_ergo.drv | 3 +- lib/drivers/why3.drv | 2 + src/core/ident.ml | 4 ++ src/core/ident.mli | 5 ++ src/main.ml | 133 +++++++++++++++++++++++++++++------ src/output/driver.ml | 29 +++++++- src/output/driver.mli | 4 ++ src/output/driver_ast.mli | 1 + src/output/driver_lexer.mll | 1 + src/output/driver_parser.mly | 3 +- 11 files changed, 166 insertions(+), 28 deletions(-) create mode 100644 lib/drivers/why3.drv diff --git a/Makefile.in b/Makefile.in index bc230b7d49..a8b7d741f1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -144,8 +144,11 @@ bin/top: $(CMO) ocamlmktop $(BFLAGS) -o $@ nums.cma $^ test: bin/why.byte - ocamlrun -bt bin/why.byte --print-stdout -I lib/prelude/ src/test.why - bin/why.byte --driver lib/drivers/alt_ergo.drv -I lib/prelude/ src/test.why > ergo.why + mkdir -p output_why3 + ocamlrun -bt bin/why.byte --debug -I lib/prelude/ --driver lib/drivers/why3.drv \ + --output output_why3 src/test.why + bin/why.byte --driver lib/drivers/alt_ergo.drv -I lib/prelude/ \ + --output - --goal Test.G src/test.why > ergo.why timeout 3 alt-ergo ergo.why testl: bin/whyl.byte @@ -597,6 +600,8 @@ clean:: rm -f bin/why-cpulimit rm -f lib/coq*/*.vo lib/coq*/*~ rm -f $(GENERATED) + rm -rf output_why3 + rm -f ergo.why # make -C atp clean # make -C doc clean # if test -d examples-v7; then \ diff --git a/lib/drivers/alt_ergo.drv b/lib/drivers/alt_ergo.drv index 55a964c117..b35b128406 100644 --- a/lib/drivers/alt_ergo.drv +++ b/lib/drivers/alt_ergo.drv @@ -4,8 +4,9 @@ prelude "(* this is a prelude for Alt-Ergo*)" printer "alt-ergo" - +filename "%f-%t-%s.why" call_on_file "alt-ergo %s" + (* tranformations "simplify_recursive_definition" diff --git a/lib/drivers/why3.drv b/lib/drivers/why3.drv new file mode 100644 index 0000000000..25d25b2cde --- /dev/null +++ b/lib/drivers/why3.drv @@ -0,0 +1,2 @@ +printer "why3" +filename "%f-%t-%s.why" \ No newline at end of file diff --git a/src/core/ident.ml b/src/core/ident.ml index f0a8d392f4..4ca6a1fc53 100644 --- a/src/core/ident.ml +++ b/src/core/ident.ml @@ -68,6 +68,10 @@ let id_derive_long sh ln id = create_ident sh ln (Derived id) let id_clone id = create_ident id.id_short id.id_long (Derived id) let id_dup id = { id with id_tag = -1 } +(* Utils *) +let rec derived_from i1 i2 = + i1 == i2 || (match i1.id_origin with Derived i3 -> derived_from i1 i2 | _ -> false) + (** Unique names for pretty printing *) type ident_printer = diff --git a/src/core/ident.mli b/src/core/ident.mli index 20722d9631..f21e16ee9e 100644 --- a/src/core/ident.mli +++ b/src/core/ident.mli @@ -59,6 +59,11 @@ val id_clone : ident -> preid (* create a duplicate pre-ident *) val id_dup : ident -> preid +(* Utils *) +val derived_from : ident -> ident -> bool + +(* derived_from i1 i2 is true if i1 is derived from i2 *) + (** Unique persistent names for pretty printing *) type ident_printer diff --git a/src/main.ml b/src/main.ml index 21611975bc..22a751d6d7 100644 --- a/src/main.ml +++ b/src/main.ml @@ -21,15 +21,20 @@ open Format open Theory open Driver -let files = ref [] +let files = Queue.create () let parse_only = ref false let type_only = ref false let debug = ref false let loadpath = ref [] -let print_stdout = ref false -let simplify_recursive = ref false -let inlining = ref false let driver = ref None +type which_goals = + | Gall + | Gtheory of string + | Ggoal of string +let which_goals = ref Gall +let timeout = ref 10 +let call = ref false +let output = ref None let () = Arg.parse @@ -37,19 +42,31 @@ let () = "--type-only", Arg.Set type_only, "stops after type-checking"; "--debug", Arg.Set debug, "sets the debug flag"; "-I", Arg.String (fun s -> loadpath := s :: !loadpath), - "<dir> adds dir to the loadpath"; - "--print-stdout", Arg.Set print_stdout, "print the results to stdout"; - "--simplify-recursive", Arg.Set simplify_recursive, - "simplify recursive definition"; - "--inline", Arg.Set inlining, "inline the definition not recursive"; + "<dir> adds dir to the loadpath"; + "--all_goals", Arg.Unit (fun () -> which_goals := Gall), + "apply on all the goals of the file"; + "--goals_of", Arg.String (fun s -> which_goals := Gtheory s), + "apply on all the goals of the theory given (ex. --goal T)"; + "--goal", Arg.String (fun s -> which_goals := Ggoal s), + "apply only on the goal given (ex. --goal T.g)"; + "--output", Arg.String (fun s -> output := Some s), + "choose to output each goals in the directory given.\ + Can't be used with --call"; + "--call", Arg.Set call, + "choose to call the prover on each goals.\ + Can't be used with --output"; (* Why not? *) "--driver", Arg.String (fun s -> driver := Some s), - "<file> set the driver file"; + "<file> set the driver file"; ] - (fun f -> files := f :: !files) + (fun f -> Queue.push f files) "usage: why [options] files..." -let in_emacs = Sys.getenv "TERM" = "dumb" +let () = + match !output with + | None when not !call -> type_only := true + | _ -> () +(* let transformation l = let t1 = Simplify_recursive_definition.t in let t2 = Inlining.all in @@ -60,7 +77,7 @@ let transformation l = let c = if !inlining then Transform.apply t2 c else c in (t,c)) l - +*) let rec report fmt = function | Lexer.Error e -> fprintf fmt "lexical error: %a" Lexer.report e; @@ -76,16 +93,14 @@ let rec report fmt = function Driver.report fmt e | e -> fprintf fmt "anomaly: %s" (Printexc.to_string e) -let extract_goals ctxt = - Transform.apply Transform.split_goals ctxt - +(* let transform env l = let l = List.map (fun t -> t, Context.use_export (Context.init_context env) t) l in - let l = transformation l in + (*let l = transformation l in*) if !print_stdout then List.iter (fun (t,ctxt) -> Pretty.print_named_context @@ -94,7 +109,7 @@ let transform env l = | None -> () | Some file -> - let drv = load_driver file env in + begin match l with | (_,ctxt) :: _ -> begin match extract_goals ctxt with | g :: _ -> @@ -104,8 +119,18 @@ let transform env l = end | [] -> () end +*) + + +let extract_goals env acc th = + let ctxt = Context.use_export (Context.init_context env) th in + let l = Transform.apply Transform.split_goals ctxt in + let l = List.rev_map (fun ctxt -> (th,ctxt)) l in + List.rev_append l acc + +let file_sanitizer = Ident.sanitizer Ident.char_to_alnumus Ident.char_to_alnumus -let type_file env file = +let do_file env drv filename_printer file = if !parse_only then begin let c = open_in file in let lb = Lexing.from_channel c in @@ -114,14 +139,78 @@ let type_file env file = close_in c end else begin let m = Typing.read_file env file in - let l = Mnm.fold (fun _ th acc -> th :: acc) m [] in - transform env l + if not !type_only then + let drv = + match drv with + | None -> eprintf "a driver is needed@."; exit 1 + | Some drv -> drv in + let goals = + match !which_goals with + | Gall -> Mnm.fold (fun _ th acc -> extract_goals env acc th) m [] + | Gtheory s -> + begin + try + extract_goals env [] (Mnm.find s m) + with Not_found -> + eprintf "File %s : --goals_of : Unknown theory %s@." file s; exit 1 + end + | Ggoal s -> + let l = Str.split (Str.regexp "\\.") s in + let tname, l = + match l with + | [] | [_] -> + eprintf "--goal : Must be a qualified name (%s)@." s; + exit 1 + | a::l -> a,l in + let rec find_pr ns = function + | [] -> assert false + | [a] -> Mnm.find a ns.ns_pr + | a::l -> find_pr (Mnm.find a ns.ns_ns) l in + let th =try Mnm.find tname m with Not_found -> + eprintf "File %s : --goal : Unknown theory %s@." file tname; exit 1 in + let pr = try find_pr th.th_export l with Not_found -> + eprintf "File %s : --goal : Unknown goal %s@." file s ; exit 1 in + let goals = extract_goals env [] th in + List.filter (fun (_,ctxt) -> + match ctxt.ctxt_decl.d_node with + | Dprop (_,{pr_name = pr_name}) -> + Ident.derived_from pr_name pr.pr_name + | _ -> assert false) goals in + let file = + let file = Filename.basename file in + let file = Filename.chop_extension file in + Ident.id_unique filename_printer + (Ident.id_register (Ident.id_fresh file)) in + match !output with + | None -> () + | Some dir -> + let ident_printer = Ident.create_ident_printer + ~sanitizer:file_sanitizer [] in + List.iter + (fun (th,ctxt) -> + let cout = + if dir = "-" + then stdout + else + let filename = + Driver.filename_of_goal drv ident_printer + file th.th_name.Ident.id_short ctxt in + let filename = Filename.concat dir filename in + open_out filename in + let fmt = formatter_of_out_channel cout in + fprintf fmt "%a@?" (Driver.print_context drv) ctxt; + close_out cout) goals end let () = try let env = create_env (Typing.retrieve !loadpath) in - List.iter (type_file env) !files + let drv = match !driver with + | None -> None + | Some file -> Some (load_driver file env) in + let filename_printer = Ident.create_ident_printer + ~sanitizer:file_sanitizer [] in + Queue.iter (do_file env drv filename_printer) files with e when not !debug -> eprintf "%a@." report e; exit 1 diff --git a/src/output/driver.ml b/src/output/driver.ml index baf7412633..b98ed4c27e 100644 --- a/src/output/driver.ml +++ b/src/output/driver.ml @@ -31,7 +31,7 @@ open Str let opt_search_forward re s pos = try Some(search_forward re s pos) with Not_found -> None -let global_substitute expr repl_fun text fmt = +let global_substitute_fmt expr repl_fun text fmt = let rec replace start last_was_empty = let startpos = if last_was_empty then start + 1 else start in if startpos > String.length text then @@ -125,6 +125,7 @@ and driver = { drv_call_file : string option; drv_regexps : (string * prover_answer) list; drv_prelude : string option; + drv_filename : string option; drv_rules : theory_rules list; drv_thprelude : string Hid.t; (* the first is the translation only for this ident, the second is also for representant *) @@ -263,6 +264,7 @@ let load_driver file env = let printer = ref None in let call_stdin = ref None in let call_file = ref None in + let filename = ref None in let regexps = ref [] in let set_or_raise loc r v error = if !r <> None then errorm ~loc "duplicate %s" error @@ -281,6 +283,7 @@ let load_driver file env = | RegexpInvalid s -> regexps:=(s,Invalid)::!regexps | RegexpUnknown (s1,s2) -> regexps:=(s1,Unknown s2)::!regexps | RegexpFailure (s1,s2) -> regexps:=(s1,Failure s2)::!regexps + | Filename s -> set_or_raise loc filename s "filename" in List.iter add f.f_global; { drv_printer = !printer; @@ -289,6 +292,7 @@ let load_driver file env = drv_call_file = !call_file; drv_regexps = !regexps; drv_prelude = !prelude; + drv_filename = !filename; drv_rules = f.f_rules; drv_thprelude = Hid.create 1; drv_theory = Hid.create 1; @@ -318,7 +322,7 @@ let syntax_arguments s print fmt l = let repl_fun s fmt = let i = int_of_string (matched_group 1 s) in print fmt args.(i-1) in - global_substitute regexp_arg_pos repl_fun s fmt + global_substitute_fmt regexp_arg_pos repl_fun s fmt (** using drivers *) @@ -331,10 +335,31 @@ let print_context drv fmt ctxt = match drv.drv_printer with List.iter (load_rules drv) drv.drv_rules; f drv fmt ctxt +let regexp_filename = Str.regexp "%\\([a-z]\\)" + +let filename_of_goal drv ident_printer filename theory_name ctxt = + match drv.drv_filename with + | None -> errorm "no filename syntax given" + | Some f -> + let pr_name = match ctxt.ctxt_decl.d_node with + | Dprop (Pgoal,{pr_name=pr_name}) -> pr_name + | _ -> errorm "the bottom of this context is not a goal" in + let repl_fun s = + let i = matched_group 1 s in + match i with + | "f" -> filename + | "t" -> theory_name + | "s" -> id_unique ident_printer pr_name + | _ -> errorm "substitution variable are only %%f %%t and %%s" in + global_substitute regexp_filename repl_fun f + + let call_prover drv ctx = assert false (*TODO*) let call_prover_on_file drv filename = assert false (*TODO*) let call_prover_on_channel drv filename ic = assert false (*TODO*) + + (* Local Variables: compile-command: "unset LANG; make -C ../.. test" diff --git a/src/output/driver.mli b/src/output/driver.mli index 8ebe3e49df..4181db7198 100644 --- a/src/output/driver.mli +++ b/src/output/driver.mli @@ -48,6 +48,10 @@ val register_printer : string -> printer -> unit val print_context : printer +val filename_of_goal : driver -> Ident.ident_printer -> + string -> string -> context -> string +(* filename_of_goal printer file_ident theory_ident ctxt *) + type prover_answer = | Valid | Invalid diff --git a/src/output/driver_ast.mli b/src/output/driver_ast.mli index 39c7401976..5c358cf19a 100644 --- a/src/output/driver_ast.mli +++ b/src/output/driver_ast.mli @@ -46,6 +46,7 @@ type global = | RegexpInvalid of string | RegexpUnknown of string * string | RegexpFailure of string * string + | Filename of string type file = { f_global : (loc * global) list; diff --git a/src/output/driver_lexer.mll b/src/output/driver_lexer.mll index 2d0ba6ec8d..2e090c8abe 100644 --- a/src/output/driver_lexer.mll +++ b/src/output/driver_lexer.mll @@ -44,6 +44,7 @@ "logic", LOGIC; "type", TYPE; "prop", PROP; + "filename", FILENAME; ] } diff --git a/src/output/driver_parser.mly b/src/output/driver_parser.mly index 1a709c81e2..5b11612079 100644 --- a/src/output/driver_parser.mly +++ b/src/output/driver_parser.mly @@ -32,7 +32,7 @@ %token THEORY END SYNTAX REMOVE TAG PRELUDE PRINTER CALL_ON_FILE CALL_ON_STDIN %token VALID INVALID UNKNOWN FAIL %token UNDERSCORE LEFTPAR RIGHTPAR CLONED DOT EOF -%token LOGIC TYPE PROP +%token LOGIC TYPE PROP FILENAME %type <Driver_ast.file> file %start file @@ -58,6 +58,7 @@ global: | INVALID STRING { RegexpInvalid $2 } | UNKNOWN STRING STRING { RegexpUnknown ($2, $3) } | FAIL STRING STRING { RegexpFailure ($2, $3) } +| FILENAME STRING { Filename $2 } ; list0_theory: -- GitLab