]> matita.cs.unibo.it Git - helm.git/blob - helm/software/matita/rottener.ml
avoid rottening of constructor names in pattern matchings
[helm.git] / helm / software / matita / rottener.ml
1 (* Copyright (C) 2007, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://helm.cs.unibo.it/
24  *)
25
26 open Printf
27
28 module Ast = GrafiteAst
29 module Pt = CicNotationPt
30
31 let error_token = "O"
32 let error_token_len = String.length error_token
33
34 let has_toplevel_term = function
35   | GrafiteParser.LSome (Ast.Executable (_, Ast.Command (_, Ast.Obj (loc, (
36         Pt.Theorem ((`Definition | `Lemma | `Theorem), _, _, _)
37       (*| Pt.Inductive _*)
38       (*| Pt.Record _*)
39     ))))) ->
40       true
41   | _ -> false
42
43 let flush_token_stream (stream, loc_func) =
44   let tok_count = ref ~-1 in
45   let rec aux acc =
46     let next_tok =
47       try Some (Stream.next stream) with Stream.Failure -> None in
48     match next_tok with
49     | None | Some ("EOI", _) -> List.rev acc
50     | Some tok ->
51         incr tok_count;
52         aux ((tok, loc_func !tok_count) :: acc) in
53   aux []
54
55 let rotten_script ~fname statement =
56   (* XXX terribly inefficient: the same script is read several times ... *)
57   let lexer = CicNotationLexer.level2_ast_lexer in
58   let token_stream, loc_func =
59     lexer.Token.tok_func (Obj.magic (Ulexing.from_utf8_string statement)) in
60   let tokens = flush_token_stream (token_stream, loc_func) in
61   let target_token, target_pos =
62     let rec sanitize_tokens acc = function
63       | [] -> List.rev acc
64       | (("IDENT",
65           ("theorem" | "definition" | "lemma" | "record" | "inductive")), _)
66         :: (("IDENT", _), _) :: tl ->
67           (* avoid rottening of object names *)
68           sanitize_tokens acc tl
69       | (("SYMBOL", ("∀" | "λ" | "Π")), _) :: (("IDENT", _), _) :: tl ->
70           (* avoid rottening of binders *)
71           let rec remove_args = function
72             | (("SYMBOL", ","), _) :: (("IDENT", _), _) :: tl ->
73                 remove_args tl
74             | tl -> tl in
75           sanitize_tokens acc (remove_args tl)
76       | (("SYMBOL", "⇒"), _) as hd :: tl ->
77           (* avoid rottening of constructor names in pattern matching *)
78           let rec remove_until_branch_start = function
79             | (("SYMBOL", ("|" | "[")), _) :: tl -> tl
80             | hd :: tl -> remove_until_branch_start tl
81             | [] -> [] in
82           sanitize_tokens (hd :: remove_until_branch_start acc) tl
83       | hd :: tl -> (* every other identfier can be rottened! *)
84           sanitize_tokens (hd :: acc) tl in
85     let idents =
86       List.filter (function (("IDENT", _), _) -> true | _ -> false)
87         (sanitize_tokens [] tokens) in
88     List.nth idents (Random.int (List.length idents))
89   in
90   let start_pos, end_pos =
91     Glib.Utf8.offset_to_pos statement 0 (Ploc.first_pos target_pos),
92     Glib.Utf8.offset_to_pos statement 0 (Ploc.last_pos target_pos) in
93   let statement' =
94     (* positions in bytecount *)
95     String.sub statement 0 start_pos
96     ^ "O"
97     ^ String.sub statement end_pos (String.length statement - end_pos) in
98   let script = HExtlib.input_file fname in
99   let matches =
100     let rex =
101       Pcre.regexp ~flags:[`DOTALL]
102         (sprintf "^(.*)(%s)(.*)$" (Pcre.quote statement)) in
103     try
104       Pcre.extract ~rex script
105     with Not_found -> assert false
106   in
107   let trailer = (* trailing comment with machine parseable error location *)
108     let preamble_len = String.length matches.(1) in
109     sprintf "\n(*\nerror-at: %d-%d\n*)\n" (preamble_len + start_pos)
110       (preamble_len + start_pos + error_token_len) in
111   let script' = sprintf "%s%s%s%s" matches.(1) statement' matches.(3) trailer in
112   let md5 = Digest.to_hex (Digest.string script') in
113   HExtlib.output_file
114     ~filename:(sprintf "%s.rottened.%s.ma" (Filename.chop_extension fname) md5)
115     ~text:script'
116
117 let grep () =
118   let recursive = ref false in
119   let spec = [
120     "-r", Arg.Set recursive, "enable directory recursion";
121   ] in
122   MatitaInit.add_cmdline_spec spec;
123   MatitaInit.initialize_all ();
124   let include_paths =
125     Helm_registry.get_list Helm_registry.string "matita.includes" in
126   let status =
127     CicNotation2.load_notation ~include_paths
128       BuildTimeConf.core_notation_script in
129   let path =
130     match Helm_registry.get_list Helm_registry.string "matita.args" with
131     | [ path ] -> path
132     | _ -> MatitaInit.die_usage () in
133   let grep_fun =
134     if !recursive then
135       (fun dirname ->
136         let sane_statements =
137           GrafiteWalker.rgrep_statement ~status ~dirname has_toplevel_term in
138         List.iter (fun (fname, statement) -> rotten_script ~fname statement)
139           sane_statements)
140     else
141       (fun fname ->
142         let sane_statements =
143           GrafiteWalker.grep_statement ~status ~fname has_toplevel_term in
144         List.iter (fun statement -> rotten_script ~fname statement)
145           sane_statements)
146   in
147   grep_fun path
148
149 let handle_localized_exns f arg =
150   try
151     f arg
152   with HExtlib.Localized (loc, exn) ->
153     let loc_begin, loc_end = HExtlib.loc_of_floc loc in
154     eprintf "Error at %d-%d: %s\n%!" loc_begin loc_end (Printexc.to_string exn)
155
156 let _ =
157   Random.init 17;
158   handle_localized_exns grep ()
159