]> matita.cs.unibo.it Git - helm.git/blob - helm/software/matita/rottener.ml
9888e11e7ddf4ac4137c09e93e76e3d543cb366c
[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 = function
63       | [] -> []
64       | (("IDENT",
65           ("theorem" | "definition" | "lemma" | "record" | "inductive")), _)
66         :: (("IDENT", _), _) :: tl
67       | (("SYMBOL", ("∀" | "λ" | "Π")), _) :: (("IDENT", _), _) :: tl ->
68           let rec remove_args = function
69             | (("SYMBOL", ","), _) :: (("IDENT", _), _) :: tl ->
70                 remove_args tl
71             | tl -> tl in
72           let tl' = remove_args tl in
73           sanitize_tokens tl'
74       | hd :: tl -> hd :: sanitize_tokens tl in
75     let idents =
76       List.filter (function (("IDENT", _), _) -> true | _ -> false)
77         (sanitize_tokens tokens) in
78     List.nth idents (Random.int (List.length idents))
79   in
80   let start_pos, end_pos =
81     Glib.Utf8.offset_to_pos statement 0 (Ploc.first_pos target_pos),
82     Glib.Utf8.offset_to_pos statement 0 (Ploc.last_pos target_pos) in
83   let statement' =
84     (* positions in bytecount *)
85     String.sub statement 0 start_pos
86     ^ "O"
87     ^ String.sub statement end_pos (String.length statement - end_pos) in
88   let script = HExtlib.input_file fname in
89   let matches =
90     let rex =
91       Pcre.regexp ~flags:[`DOTALL]
92         (sprintf "^(.*)(%s)(.*)$" (Pcre.quote statement)) in
93     try
94       Pcre.extract ~rex script
95     with Not_found -> assert false
96   in
97   let trailer = (* trailing comment with machine parseable error location *)
98     let preamble_len = String.length matches.(1) in
99     sprintf "\n(*\nerror-at: %d-%d\n*)\n" (preamble_len + start_pos)
100       (preamble_len + start_pos + error_token_len) in
101   let script' = sprintf "%s%s%s%s" matches.(1) statement' matches.(3) trailer in
102   let md5 = Digest.to_hex (Digest.string script') in
103   HExtlib.output_file
104     ~filename:(sprintf "%s.rottened.%s.ma" (Filename.chop_extension fname) md5)
105     ~text:script'
106
107 let grep () =
108   let recursive = ref false in
109   let spec = [
110     "-r", Arg.Set recursive, "enable directory recursion";
111   ] in
112   MatitaInit.add_cmdline_spec spec;
113   MatitaInit.initialize_all ();
114   let include_paths =
115     Helm_registry.get_list Helm_registry.string "matita.includes" in
116   let status =
117     CicNotation2.load_notation ~include_paths
118       BuildTimeConf.core_notation_script in
119   let path =
120     match Helm_registry.get_list Helm_registry.string "matita.args" with
121     | [ path ] -> path
122     | _ -> MatitaInit.die_usage () in
123   let grep_fun =
124     if !recursive then
125       (fun dirname ->
126         let sane_statements =
127           GrafiteWalker.rgrep_statement ~status ~dirname has_toplevel_term in
128         List.iter (fun (fname, statement) -> rotten_script ~fname statement)
129           sane_statements)
130     else
131       (fun fname ->
132         let sane_statements =
133           GrafiteWalker.grep_statement ~status ~fname has_toplevel_term in
134         List.iter (fun statement -> rotten_script ~fname statement)
135           sane_statements)
136   in
137   grep_fun path
138
139 let handle_localized_exns f arg =
140   try
141     f arg
142   with HExtlib.Localized (loc, exn) ->
143     let loc_begin, loc_end = HExtlib.loc_of_floc loc in
144     eprintf "Error at %d-%d: %s\n%!" loc_begin loc_end (Printexc.to_string exn)
145
146 let _ =
147   Random.init 17;
148   handle_localized_exns grep ()
149