]> matita.cs.unibo.it Git - helm.git/blob - helm/software/helena/src/toplevel/top.ml
exportation to \lambda\delta representation in elpi
[helm.git] / helm / software / helena / src / toplevel / top.ml
1 (*
2     ||M||  This file is part of HELM, an Hypertextual, Electronic        
3     ||A||  Library of Mathematics, developed at the Computer Science     
4     ||T||  Department, University of Bologna, Italy.                     
5     ||I||                                                                
6     ||T||  HELM is free software; you can redistribute it and/or         
7     ||A||  modify it under the terms of the GNU General Public License   
8     \   /  version 2 or (at your option) any later version.              
9      \ /   This software is distributed as is, NO WARRANTY.              
10       V_______________________________________________________________ *)
11
12 module KF = Filename
13 module KP = Printf
14 module KS = String
15
16 module U  = NUri
17 module C  = Cps
18 module L  = Log
19 module Y  = Time
20 module P  = Marks
21 module G  = Options
22 module H  = Hierarchy
23 module N  = Layer
24 module E  = Entity
25 module O  = Output
26 module DO = CrgOutput
27 module TD = TxtCrg
28 module AA = AutProcess
29 module AO = AutOutput
30 module AD = AutCrg
31 module XL = XmlLibrary
32 module XD = XmlCrg
33 module B  = Brg
34 module BD = BrgCrg
35 module BO = BrgOutput
36 module BR = BrgReduction
37 module BU = BrgUntrusted
38 module BG = BrgGrafite
39 module BA = BrgGallina
40 module BP = BrgELPI
41 module ZD = BagCrg
42 module ZO = BagOutput
43 module ZT = BagType
44 module ZU = BagUntrusted
45
46 type status = {
47    kst: N.status;
48    tst: TD.status;
49    pst: AA.status;
50    ast: AD.status;
51    ac : AO.counters;
52    dc : DO.counters;
53    bc : BO.counters;
54    zc : ZO.counters;
55    mst: B.manager option;
56 }
57
58 let level = 0
59
60 let bag_error st s msg =
61    L.error st.kst ZO.specs (L.Warn s :: msg) 
62
63 let brg_error st s msg =
64    L.error st.kst BR.specs (L.Warn s :: msg)
65
66 let initial_status () = {
67    kst = N.initial_status ();
68    tst = TD.initial_status ();
69    pst = AA.initial_status ();
70    ast = AD.initial_status ();
71    ac  = AO.initial_counters;
72    dc  = DO.initial_counters;
73    bc  = BO.initial_counters;
74    zc  = ZO.initial_counters;
75    mst = None;
76 }
77
78 let refresh_status st = {st with
79    kst = N.refresh_status st.kst;
80    tst = TD.refresh_status st.tst;
81    ast = AD.refresh_status st.ast;
82 }
83
84 (* kernel related ***********************************************************)
85
86 type kernel_entity = BrgEntity of Brg.entity
87                    | BagEntity of Bag.entity
88                    | CrgEntity of Crg.entity
89
90 let print_counters st = function
91    | G.V4 -> DO.print_counters C.start st.dc
92    | G.V3 -> BO.print_counters C.start st.bc
93    | G.V0 -> ZO.print_counters C.start st.zc
94
95 let xlate_entity st entity = match !G.kernel, entity with
96    | G.V3, CrgEntity e -> 
97       let f e = (BrgEntity e) in E.xlate f BD.brg_of_crg e
98    | G.V0, CrgEntity e -> 
99       let f e = (BagEntity e) in E.xlate f (ZD.bag_of_crg st.kst) e
100    | _, entity          -> entity
101
102 let pp_progress e =
103    let f _ na u =
104       let s = U.string_of_uri u in
105       L.warn 2 (KP.sprintf "[%u] <%s>" na.E.n_apix s);
106    in
107    Y.utime_stamp "intermediate";
108    match e with
109       | CrgEntity e -> E.common f e
110       | BrgEntity e -> E.common f e
111       | BagEntity e -> E.common f e      
112
113 let count_entity st = function
114    | BrgEntity e -> {st with bc = BO.count_entity C.start st.bc e}
115    | BagEntity e -> {st with zc = ZO.count_entity C.start st.zc e}
116    | CrgEntity e -> {st with dc = DO.count_entity C.start st.dc e}
117
118 let export_entity st = function
119    | CrgEntity e -> XL.export_entity (XD.export_term st.kst) e
120    | BrgEntity e -> XL.export_entity (BO.export_term st.kst) e
121    | BagEntity e -> XL.export_entity (ZO.export_term st.kst) e
122
123 let type_check st k =
124    let brg_err msg = brg_error st "Type Error" msg; failwith "Interrupted" in
125    let bag_err msg = bag_error st "Type Error" msg; failwith "Interrupted" in
126    let ok _ _ = st in
127    match k with
128       | BrgEntity entity -> BU.type_check brg_err ok st.kst entity
129       | BagEntity entity -> ZU.type_check bag_err ok st.kst entity
130       | CrgEntity _      -> st
131
132 let validate st k =
133    let brg_err msg = brg_error st "Validation Error" msg; failwith "Interrupted" in
134    let ok _ = st in
135    match k with
136       | BrgEntity entity -> BU.validate brg_err ok st.kst entity
137       | BagEntity _      -> st
138       | CrgEntity _      -> st
139
140 let manager st output_entity = function
141    | BrgEntity entity -> 
142       if output_entity st.kst entity then st else
143       begin L.warn level "manager exportation stopped"; {st with mst = None} end
144    | BagEntity _      -> st
145    | CrgEntity _      -> st
146
147 (* extended lexer ***********************************************************)
148
149 type 'token lexer = {
150    parse : Lexing.lexbuf -> 'token;
151    mutable tokbuf: 'token option;
152    mutable unget : bool
153 }
154
155 let initial_lexer parse = {
156    parse = parse; tokbuf = None; unget = false
157 }
158
159 let token xl lexbuf = match xl.tokbuf with
160    | Some token when xl.unget ->   
161       xl.unget <- false; token
162    | _                        ->
163       let token = xl.parse lexbuf in
164       xl.tokbuf <- Some token; token
165
166 (* input related ************************************************************)
167
168 type input = Text | Automath
169
170 type input_entity = TxtEntity of Txt.command
171                   | AutEntity of Aut.command
172                   | NoEntity
173
174 let type_of_input name =
175    if KF.check_suffix name ".hln" then Text 
176    else if KF.check_suffix name ".aut" then 
177       let _ = H.set_sorts 0 ["Set"; "Prop"] in
178       assert (H.set_graph "Z2");
179       Automath
180    else begin
181       L.warn level (KP.sprintf "Unknown file type: %s" name); exit 2
182    end
183
184 let txt_xl = initial_lexer TxtLexer.token 
185
186 let aut_xl = initial_lexer AutLexer.token 
187
188 let parbuf = ref [] (* parser buffer *)
189
190 let gen_text command = 
191    parbuf := TxtEntity command :: !parbuf
192
193 let entity_of_input lexbuf i = match i, !parbuf with
194    | Automath, _    -> 
195       begin match AutParser.entry (token aut_xl) lexbuf with
196          | Some e -> aut_xl.unget <- true; AutEntity e
197          | None   -> NoEntity
198       end     
199    | Text, []       -> 
200       begin match TxtParser.entry (token txt_xl) lexbuf with
201          | Some e -> txt_xl.unget <- true; TxtEntity e
202          | None   -> NoEntity
203       end
204    | Text, hd :: tl ->
205       parbuf := tl; hd
206
207 let process_input f st = function 
208    | AutEntity e     ->
209       let f pst e = f {st with pst = pst} (AutEntity e) in
210       AA.process_command f st.pst e
211    | xe              -> f st xe
212
213 let count_input st = function
214    | AutEntity e -> {st with ac = AO.count_command C.start st.ac e}
215    | xe          -> st
216
217 (****************************************************************************)
218
219 let version = ref true
220 let preprocess = ref false
221 let root = ref ""
222 let export = ref false
223 let st = ref (initial_status ())
224 let streaming = ref false (* parsing style (temporary) *)
225
226 let process_2 st entity =
227    let st = if !G.summary then count_entity st entity else st in
228    let st = 
229       if !G.stage >= 3 then 
230          let f = if !version then validate else type_check in f st entity
231       else st
232    in
233    if !export then export_entity st entity;
234    match st.mst with
235      | None                    -> st
236      | Some (export_entity, _) -> manager st export_entity entity
237
238 let process_1 st entity = 
239    if !G.trace >= 3 then pp_progress entity;
240    let st = if !G.summary then count_entity st entity else st in
241    if !export && !G.stage = 1 then export_entity st entity;
242    if !G.stage >= 2 then process_2 st (xlate_entity st entity) else st 
243
244 let process_0 st entity = 
245    let f st entity =
246       if !G.stage = 0 then st else
247       match entity with
248          | AutEntity e -> 
249             let err ast = {st with ast = ast} in
250             let g ast e = process_1 {st with ast = ast} (CrgEntity e) in
251             AD.crg_of_aut err g st.kst st.ast e
252          | TxtEntity e -> 
253             let crr tst = {st with tst = tst} in
254             let d tst e = process_1 {st with tst = tst} (CrgEntity e) in
255             TD.crg_of_txt crr d gen_text st.tst e
256          | NoEntity    -> assert false
257    in
258    let st = if !G.summary then count_input st entity else st in 
259    if !preprocess then process_input f st entity else f st entity
260
261 let process_nostreaming st lexbuf input =
262    let id x = x in
263    let rec aux1 book = match entity_of_input lexbuf input with
264       | NoEntity -> List.rev book
265       | e        -> aux1 (id e :: book)   
266    in
267    let rec aux2 st = function
268       | []           -> st
269       | entity :: tl -> aux2 (process_0 st entity) tl
270    in
271    aux2 st (aux1 [])
272
273 let process_streaming st lexbuf input =
274    let rec aux st = match entity_of_input lexbuf input with
275       | NoEntity -> st
276       | e        -> aux (process_0 st e)
277    in
278    aux st
279
280 (****************************************************************************)
281
282 let process st name =
283    let process = if !streaming then process_streaming else process_nostreaming in
284    let input = type_of_input name in
285    let ich = open_in name in
286    let lexbuf = Lexing.from_channel ich in 
287    let st = process st lexbuf input in
288    close_in ich;
289    st, input
290
291 let main = 
292    let print_version () = L.warn level (G.version_string ^ "\n"); exit 0 in
293    let set_hierarchy s = 
294       if H.set_graph s then () else 
295          L.warn level (KP.sprintf "Unknown type hierarchy: %s" s)
296    in
297    let set_kernel = function
298       | "V3" -> G.kernel := G.V3
299       | "V0" -> G.kernel := G.V0
300       | s    -> L.warn level (KP.sprintf "Unknown kernel version: %s" s)
301    in
302    let set_trace i = 
303       if !G.trace = 0 && i > 0 then Y.gmtime G.version_string;
304       if !G.trace > 0 && i = 0 then Y.utime_stamp "at exit";
305       G.trace := i;
306       if i <= 1 then G.summary := false;
307       if i <= 1 then preprocess := false
308    in
309    let set_summary () = 
310       if !G.trace >= 2 then G.summary := true
311    in 
312    let set_preprocess () = 
313       if !G.trace >= 2 then begin preprocess := true; G.summary := true end 
314    in
315    let set_manager s = match KS.lowercase s with
316       | "v8"   -> G.manager := G.Coq
317       | "ma2"  -> G.manager := G.Matita
318       | "elpi" -> G.manager := G.ELPI
319       | s      -> L.warn level (KP.sprintf "Unknown manager: %s" s) 
320    in
321    let clear_options () =
322       export := false; preprocess := false;
323       root := "";
324       G.clear (); H.clear (); O.clear_reductions ();
325       streaming := false;
326       version := true
327    in
328    let process_file name =
329       if !G.trace >= 2 then L.warn 1 (KP.sprintf "Processing file: %s" name);
330       if !G.trace >= 2 then Y.utime_stamp "started";
331       let base_name = Filename.chop_extension (Filename.basename name) in
332       let cover = KF.concat !root base_name in
333       if !G.stage <= 1 then G.kernel := G.V4;
334       G.cover := cover;
335       begin match !G.manager with
336          | G.Coq    -> st := {!st with mst = Some (BA.open_out base_name)}
337          | G.Matita -> st := {!st with mst = Some (BG.open_out base_name)}
338          | G.ELPI   -> st := {!st with mst = Some (BP.open_out base_name)}
339          | G.Quiet  -> ()
340       end;
341       P.clear_marks ();
342       let sst, input = process (refresh_status !st) name in
343       st := begin match sst.mst with 
344          | None                -> sst
345          | Some (_, close_out) -> close_out (); {sst with mst = None}
346       end;
347       if !G.trace >= 2 then Y.utime_stamp "processed";
348       if !G.summary then begin
349          AO.print_counters C.start !st.ac;
350          if !preprocess then AO.print_process_counters C.start !st.pst;
351          if !G.stage >= 1 then print_counters !st G.V4;
352          if !G.stage >= 2 then print_counters !st !G.kernel;
353          if !G.stage >= 3 then O.print_reductions ()
354       end
355    in
356    let exit () =
357       if !G.trace >= 1 then Y.utime_stamp "at exit"
358    in
359    let help = 
360       "Usage: helena [ -LPVXdgilopqtx1 | -Ts <number> | -MO <dir> | -c <file> | -ahkmr <string> ]* [ <file> ]*\n\n" ^
361       "Trace levels: 0 just errors (default), 1 time stamps, 2 processed files, 3 processed objects,\n" ^
362       "              4 typing information, 5 conversion information, 6 reduction information,\n" ^
363       "              7 level disambiguation\n\n" ^
364       "Stages: 0 parsing, 1 to intermediate, 2 to untrusted, 3 to trusted (default)\n\n" ^
365       "Supported manages: \"ma2\" (Grafite NG), \"v8\" (Gallina 8), \"elpi\" (lambda-Prolog)\n" 
366    in
367    let help_L = " show lexer debug information" in 
368    let help_M = "<dir>  set location of output directory (manager) to <dir> (default: current directory)" in
369    let help_O = "<dir>  set location of output directory (XML) to <dir> (default: current directory)" in
370    let help_P = " show parser debug information" in 
371    let help_T = "<number>  set trace level (see above)" in
372    let help_V = " show version information" in
373    let help_X = " clear options" in
374    
375    let help_a = "<string>  set prefix of numeric identifiers (default: empty)" in
376    let help_c = "<file>  set preamble to this file (default: empty)" in
377    let help_d = " show summary information (requires trace >= 2)" in
378    let help_g = " always expand global definitions" in
379    let help_h = "<string>  set type hierarchy (default: \"Z1\")" in
380    let help_i = " show local references by index" in
381    let help_k = "<string>  set kernel version (default: \"V3\")" in
382    let help_l = " disambiguate binders level (Automath)" in
383    let help_m = "<string>  export kernel entities for this manager (see above, default: no manager)" in
384    let help_o = " activate sort inclusion (default: false)" in
385    let help_p = " preprocess source (Automath)" in
386    let help_q = " disable quotation of identifiers" in
387    let help_r = "<string>  set initial segment of URI hierarchy (default: empty)" in
388    let help_s = "<number>  set translation stage (see above)" in
389    let help_t = " type check [version 1]" in
390    let help_x = " export kernel entities (XML)" in
391    
392    let help_1 = " parse files with streaming policy" in
393    at_exit exit;
394    Arg.parse [
395       ("-L", Arg.Set G.debug_lexer, help_L);
396       ("-M", Arg.String ((:=) G.manager_dir), help_M);
397       ("-O", Arg.String ((:=) G.xdir), help_O);
398       ("-P", Arg.Set G.debug_parser, help_P);
399       ("-T", Arg.Int set_trace, help_T);
400       ("-V", Arg.Unit print_version, help_V);
401       ("-X", Arg.Unit clear_options, help_X);
402       ("-a", Arg.String ((:=) G.alpha), help_a);
403       ("-c", Arg.String ((:=) G.preamble), help_c);
404       ("-d", Arg.Unit set_summary, help_d);
405       ("-g", Arg.Set G.expand, help_g);
406       ("-h", Arg.String set_hierarchy, help_h);
407       ("-i", Arg.Set G.indexes, help_i);
408       ("-k", Arg.String set_kernel, help_k);
409       ("-l", Arg.Set G.cc, help_l);
410       ("-m", Arg.String set_manager, help_m);      
411       ("-o", Arg.Set G.si, help_o);
412       ("-p", Arg.Unit set_preprocess, help_p);
413       ("-q", Arg.Set G.unquote, help_q);      
414       ("-r", Arg.String ((:=) root), help_r);
415       ("-s", Arg.Int ((:=) G.stage), help_s);
416       ("-t", Arg.Clear version, help_t);      
417       ("-x", Arg.Set export, help_x);
418       ("-1", Arg.Set streaming, help_1);      
419    ] process_file help