Source file command.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
(** Handling of commands. *)
open Lplib open Base open Extra
open Timed
open Common open Error open Pos
open Core open Term open Sign open Sig_state open Print
open Parsing open Syntax open Scope
open Proof
(** Type alias for a function that compiles a Lambdapi module. *)
type compiler = Path.t -> Sign.t
(** Register a check for the type of the builtin symbols "0" and "+1". *)
let _ =
let eq_noexn : term -> term -> bool = fun t u ->
let p = new_problem() in p := {!p with to_solve = [[], t, u]};
Unif.solve_noexn p && !p.unsolved = [] && !p.metas = MetaSet.empty
in
let register = Builtin.register_expected_type eq_noexn term in
let expected_zero_type ss _pos =
try
match !((StrMap.find "+1" ss.builtins).sym_type) with
| Prod(a,_) -> a
| _ -> assert false
with Not_found -> mk_Meta (LibMeta.fresh (new_problem()) mk_Type 0, [||])
in
register "0" expected_zero_type;
let expected_succ_type ss _pos =
let typ_0 =
try lift !((StrMap.find "0" ss.builtins).sym_type)
with Not_found -> _Meta (LibMeta.fresh (new_problem()) mk_Type 0) [||]
in
Bindlib.unbox (_Impl typ_0 typ_0)
in
register "+1" expected_succ_type
(** [handle_open ss p] handles the command [open p] with [ss] as the
signature state. On success, an updated signature state is returned. *)
let handle_open : sig_state -> p_path -> sig_state =
fun ss {elt=p;pos} ->
match p with
| [a] when StrMap.mem a ss.alias_path ->
fatal pos "Module aliases cannot be open."
| _ ->
if not (Path.Map.mem p !(ss.signature.sign_deps)) then
fatal pos "Module %a needs to be required first." path p;
open_sign ss (Path.Map.find p !(Sign.loaded))
(** [handle_require b ss p] handles the command [require p] (or [require
open p] if b is true) with [ss] as the signature state and [compile] the
main compile function (passed as argument to avoid cyclic dependencies).
On success, an updated signature state is returned. *)
let handle_require : compiler -> bool -> sig_state -> p_path -> sig_state =
fun compile b ss {elt=p;pos} ->
if Path.Map.mem p !(ss.signature.sign_deps) then
fatal pos "Module %a is already required." path p;
ignore (compile p);
ss.signature.sign_deps
:= Path.Map.add p StrMap.empty !(ss.signature.sign_deps);
if b then open_sign ss (Path.Map.find p !(Sign.loaded)) else ss
(** [handle_require_as compile ss p id] handles the command
[require p as id] with [ss] as the signature state and [compile] the main
compilation function passed as argument to avoid cyclic dependencies. On
success, an updated signature state is returned. *)
let handle_require_as : compiler -> sig_state -> p_path -> p_ident ->
sig_state =
fun compile ss ({elt=p;_} as mp) {elt=id;_} ->
let ss = handle_require compile false ss mp in
let alias_path = StrMap.add id p ss.alias_path in
let path_alias = Path.Map.add p id ss.path_alias in
{ss with alias_path; path_alias}
(** [handle_modifiers ms] verifies that the modifiers in [ms] are compatible.
If so, they are returned as a tuple. Otherwise, it fails. *)
let handle_modifiers : p_modifier list -> prop * expo * match_strat =
fun ms ->
let rec get_modifiers ((props, expos, strats) as acc) = function
| [] -> acc
| {elt=P_prop _;_} as p::ms -> get_modifiers (p::props, expos, strats) ms
| {elt=P_expo _;_} as e::ms -> get_modifiers (props, e::expos, strats) ms
| {elt=P_mstrat _;_} as s::ms ->
get_modifiers (props, expos, s::strats) ms
| {elt=P_opaq;_}::ms -> get_modifiers acc ms
in
let props, expos, strats = get_modifiers ([],[],[]) ms in
let prop =
match props with
| [{elt=P_prop (Assoc b);_};{elt=P_prop Commu;_}]
| [{elt=P_prop Commu;_};{elt=P_prop (Assoc b);_}] -> AC b
| _::{pos;_}::_ -> fatal pos "Incompatible or duplicated properties."
| [{elt=P_prop (Assoc _);pos}] ->
fatal pos "Associativity alone is not allowed as \
you can use a rewriting rule instead."
| [{elt=P_prop p;_}] -> p
| [] -> Defin
| _ -> assert false
in
let expo =
match expos with
| _::{pos;_}::_ ->
fatal pos "Incompatible or duplicated exposition markers."
| [{elt=P_expo e;_}] -> e
| [] -> Public
| _ -> assert false
in
let strat =
match strats with
| _::{pos;_}::_ ->
fatal pos "Incompatible or duplicated matching strategies."
| [{elt=P_mstrat s;_}] -> s
| [] -> Eager
| _ -> assert false
in
(prop, expo, strat)
(** [sr_check] indicates whether subject-reduction should be checked. *)
let sr_check = Stdlib.ref true
(** [check_rule ss syms r] checks rule [r] and returns the head symbol of the
lhs and the rule itself. *)
let check_rule : sig_state -> p_rule -> sym_rule = fun ss r ->
Console.out 3 (Color.cya "%a") Pos.pp r.pos;
Console.out 4 "%a" (Pretty.rule "rule") r;
let pr = scope_rule false ss r in
let s = pr.elt.pr_sym in
if !(s.sym_def) <> None then
fatal pr.pos "No rewriting rule can be given on a defined symbol.";
let r =
if Stdlib.(!sr_check) then Tool.Sr.check_rule pr
else Scope.rule_of_pre_rule pr
in
s, r
(** [add_rule ss syms r] checks rule [r], adds it in [ss] and returns the
head symbol of the lhs and the rule itself. *)
let add_rule : sig_state -> sym_rule -> unit = fun ss ((s,r) as x) ->
Sign.add_rule ss.signature s r;
Console.out 2 (Color.red "rule %a") sym_rule x
(** [handle_inductive_symbol ss e p strat x declpos xs a] handles the command
[e p strat symbol x xs : a] with [ss] as the signature state.
The command is at position [pos].
On success, an updated signature state and the new symbol are returned. *)
let handle_inductive_symbol : sig_state -> expo -> prop -> match_strat
-> p_ident -> popt -> p_params list -> p_term -> sig_state * sym =
fun ss expo prop mstrat ({elt=name;pos} as id) declpos xs typ ->
if Sign.mem ss.signature name then
fatal pos "Symbol %a already exists." uid name;
let typ = if xs = [] then typ else Pos.none (P_Prod(xs, typ)) in
let impl = Syntax.get_impl_term typ in
let p = new_problem() in
let typ = scope_term ~typ:true (expo = Privat) ss Env.empty typ in
let (typ, _) = Query.check_sort pos p [] typ in
if !p.metas <> MetaSet.empty then begin
fatal_msg "The type of %a has unsolved metavariables.@." uid name;
fatal pos "We have %a : %a." uid name term typ
end;
Console.out 2 (Color.red "symbol %a : %a") uid name term typ;
let r =
Sig_state.add_symbol ss expo prop mstrat false id declpos typ impl None in
sig_state := fst r; r
(** Representation of a yet unchecked proof. The structure is initialized when
the proof mode is entered, and its finalizer is called when the proof mode
is exited (i.e., when a terminator like “end” is used). Note that tactics
do not work on this structure directly, although they act on the contents
of its [pdata_state] field. *)
type proof_data =
{ pdata_sym_pos : Pos.popt (** Position of the declared symbol. *)
; pdata_state : proof_state (** Proof state. *)
; pdata_proof : p_proof (** Proof. *)
; pdata_finalize : sig_state -> proof_state -> sig_state (** Finalizer. *)
; pdata_end_pos : Pos.popt (** Position of the proof's terminator. *)
; pdata_prv : bool (** [true] iff private symbols are allowed. *) }
(** Representation of a command output. *)
type cmd_output = sig_state * proof_data option * Query.result
(** [get_proof_data compile ss cmd] tries to handle the command [cmd] with
[ss] as the signature state and [compile] as the main compilation function
processing lambdapi modules (it is passed as argument to avoid cyclic
dependencies). On success, an updated signature state is returned. When
[cmd] leads to entering the proof mode, a [proof_data] is also returned.
This structure contains the list of the tactics to be executed, as well as
the initial state of the proof. The checking of the proof is then handled
separately. Note that [Fatal] is raised in case of an error. *)
let get_proof_data : compiler -> sig_state -> p_command -> cmd_output =
fun compile ss ({elt; pos} as cmd) ->
Console.out 3 (Color.cya "%a") Pos.pp pos;
Console.out 4 "%a" Pretty.command cmd;
match elt with
| P_opaque qid ->
let s = Sig_state.find_sym ~prt:true ~prv:true ss qid in
if !(s.sym_opaq) then fatal pos "Symbol already opaque.";
s.sym_opaq := true;
(ss, None, None)
| P_query(q) -> (ss, None, Query.handle ss None q)
| P_require(b,ps) ->
(List.fold_left (handle_require compile b) ss ps, None, None)
| P_require_as(p,id) -> (handle_require_as compile ss p id, None, None)
| P_open(ps) -> (List.fold_left handle_open ss ps, None, None)
| P_rules(rs) ->
let handle_rule r (srs, map) =
let (s,r) as sr = check_rule ss r in
let h = function Some rs -> Some(r::rs) | None -> Some[r] in
sr::srs, SymMap.update s h map
in
let srs, map = List.fold_right handle_rule rs ([], SymMap.empty) in
SymMap.iter Tree.update_dtree map;
let sign = ss.signature in
Tool.Lcr.check_cps pos sign srs map;
SymMap.iter (Sign.add_rules ss.signature) map;
if !Console.verbose >= 2 then
List.iter (Console.out 2 (Color.red "rule %a") sym_rule)
(List.rev srs);
sign.Sign.sign_cp_pos :=
Tool.Lcr.update_cp_pos pos !(sign.Sign.sign_cp_pos) map;
(ss, None, None)
| P_builtin(n,qid) ->
let s = find_sym ~prt:true ~prv:true ss qid in
begin
match StrMap.find_opt n ss.builtins with
| Some s' when s' == s ->
fatal pos "Builtin \"%s\" already mapped to %a" n sym s
| _ ->
Builtin.check ss pos n s;
Console.out 2 "builtin \"%s\" ≔ %a" n sym s;
(Sig_state.add_builtin ss n s, None, None)
end
| P_notation(qid,n) ->
let s = find_sym ~prt:true ~prv:true ss qid in
let expected =
match n with
| Prefix _ | Postfix _ -> 1
| Infix _ -> 2
| Zero -> 0
| Succ _ -> 1
| Quant -> 1
| PosOne -> 0
| PosDouble -> 1
| PosSuccDouble -> 1
| IntZero -> 0
| IntPos -> 1
| IntNeg -> 1
and real = Tactic.count_products [] !(s.sym_type) in
if real < expected then
fatal pos "Notation incompatible with the type of %a" sym s;
let float_priority_from_string_priority s =
try
if String.contains s '.' then float_of_string s
else float_of_int (int_of_string s)
with Failure _ -> fatal pos "Too big number (max is %d)" max_int
in
let rec float_notation_from_string_notation n =
match n with
| Prefix s -> Prefix (float_priority_from_string_priority s)
| Postfix s -> Postfix (float_priority_from_string_priority s)
| Infix(a,s) -> Infix(a, float_priority_from_string_priority s)
| Succ x -> Succ (Option.map float_notation_from_string_notation x)
| Zero -> Zero
| Quant -> Quant
| PosOne -> PosOne
| PosDouble -> PosDouble
| PosSuccDouble -> PosSuccDouble
| IntZero -> IntZero
| IntPos -> IntPos
| IntNeg -> IntNeg
in
let n = float_notation_from_string_notation n in
Console.out 2 "notation %a %a" sym s (notation float) n;
(Sig_state.add_notation ss s n, None, None)
| P_unif_rule(h) ->
let pur = scope_rule true ss h in
let urule = Scope.rule_of_pre_rule pur in
Sign.add_rule ss.signature Unif_rule.equiv urule;
Tree.update_dtree Unif_rule.equiv [];
Console.out 2 "unif_rule %a" unif_rule urule;
(ss, None, None)
| P_coercion c ->
let pc = scope_rule false ss c in
let r = Scope.rule_of_pre_rule pc in
Sign.add_rule ss.signature Coercion.coerce r;
Tree.update_dtree Coercion.coerce [];
Console.out 2 "coercion %a" (rule_of Coercion.coerce) r;
(ss, None, None)
| P_inductive(ms, params, p_ind_list) ->
let (prop, expo, mstrat) = handle_modifiers ms in
if prop <> Defin then
fatal pos "Property modifiers cannot be used on inductive types.";
if mstrat <> Eager then
fatal pos "Pattern matching strategy modifiers cannot be used on \
inductive types.";
let add_ind_sym (ss, ind_sym_list) {elt=(id,pt,_); _} =
let (ss, ind_sym) =
let id = {id with pos} in
handle_inductive_symbol ss expo Const Eager id pos
params pt in
(ss, ind_sym::ind_sym_list)
in
let (ss, ind_sym_list_rev) =
List.fold_left add_ind_sym (ss, []) p_ind_list in
let params =
List.map (fun (idopts,typopt,_) -> (idopts,typopt,true)) params in
let add_constructors
(ss, cons_sym_list_list) {elt=(_,_,p_cons_list); _} =
let add_cons_sym (ss, cons_sym_list) (id, pt) =
let (ss, cons_sym) =
handle_inductive_symbol ss expo Const Eager id pos
params pt in
(ss, cons_sym::cons_sym_list)
in
let (ss, cons_sym_list_rev) =
List.fold_left add_cons_sym (ss, []) p_cons_list in
let cons_sym_list = List.rev cons_sym_list_rev in
(ss, cons_sym_list::cons_sym_list_list)
in
let (ss, cons_sym_list_list_rev) =
List.fold_left add_constructors (ss, []) p_ind_list
in
let ind_list =
List.fold_left2
(fun acc ind_sym cons_sym_list -> (ind_sym,cons_sym_list)::acc)
[]
ind_sym_list_rev cons_sym_list_list_rev
in
let cfg = Inductive.get_config ss pos in
let a_str, p_str, x_str = Inductive.gen_safe_prefixes ind_list in
let ind_nb_params = List.length params in
let vs, env, ind_pred_map =
Inductive.create_ind_pred_map pos cfg ind_nb_params ind_list
a_str p_str x_str
in
let rec_typ_list_rev =
Inductive.gen_rec_types cfg pos ind_list vs env ind_pred_map x_str
in
let add_recursor (ss, rec_sym_list) ind_sym rec_typ =
let rec_name = Inductive.rec_name ind_sym in
if Sign.mem ss.signature rec_name then
fatal pos "Symbol %a already exists." uid rec_name;
let (ss, rec_sym) =
Console.out 2 (Color.red "symbol %a : %a")
uid rec_name term rec_typ;
let pos = after (end_pos pos) in
let id = Pos.make pos rec_name in
let r =
Sig_state.add_symbol ss expo Defin Eager false id
None rec_typ [] None
in sig_state := fst r; r
in
(ss, rec_sym::rec_sym_list)
in
let (ss, rec_sym_list) =
List.fold_left2 add_recursor (ss, [])
ind_sym_list_rev rec_typ_list_rev
in
with_no_wrn
(Inductive.iter_rec_rules pos ind_list vs ind_pred_map)
(fun r -> add_rule ss (check_rule ss r));
List.iter (fun s -> Tree.update_dtree s []) rec_sym_list;
let ind_nb_types = List.length ind_list in
List.iter2
(fun (ind_sym, cons_sym_list) rec_sym ->
Sign.add_inductive ss.signature ind_sym cons_sym_list rec_sym
ind_nb_params ind_nb_types)
ind_list
rec_sym_list;
(ss, None, None)
| P_symbol {p_sym_mod;p_sym_nam;p_sym_arg;p_sym_typ;p_sym_trm;p_sym_prf;
p_sym_def} ->
let {elt=id; _} = p_sym_nam in
if Sign.mem ss.signature id then
fatal p_sym_nam.pos "Symbol %a already exists." uid id;
begin
match p_sym_typ, p_sym_def, p_sym_trm, p_sym_prf with
| None, true, None, Some _ -> fatal pos "missing type"
| _, true, None, None -> fatal pos "missing definition"
| _ -> ()
end;
let prop, expo, mstrat = handle_modifiers p_sym_mod in
let opaq = List.exists Syntax.is_opaq p_sym_mod in
let pdata_prv = opaq || expo = Privat in
(match p_sym_def, opaq, prop, mstrat with
| false, true, _, _ -> fatal pos "Symbol declarations cannot be opaque."
| true, _, Const, _ -> fatal pos "Definitions cannot be constant."
| true, _, _, Sequen ->
fatal pos "Definitions cannot have matching strategies."
| _ -> ());
let scope ?(typ=false) = scope_term ~typ pdata_prv ss Env.empty in
let scope ?(typ=false) t = Pos.make t.pos (scope ~typ t) in
let pt, t =
match p_sym_trm with
| Some pt ->
let pt =
if p_sym_arg = [] then pt
else let pos = Pos.(cat (end_pos p_sym_nam.pos) pt.pos) in
Pos.make pos (P_Abst(p_sym_arg, pt))
in Some pt, Some (scope pt)
| None -> None, None
in
let a, impl =
match p_sym_typ with
| None ->
let impl =
match pt with
| None -> assert false
| Some pt -> Syntax.get_impl_term pt
in None, impl
| Some a ->
let a =
if p_sym_arg = [] then a
else let pos = Pos.(cat (end_pos p_sym_nam.pos) a.pos) in
Pos.make pos (P_Prod(p_sym_arg, a))
in Some (scope ~typ:true a), Syntax.get_impl_term a
in
let p = new_problem() in
let pdata =
let t, a =
match a with
| Some {elt=a;pos} ->
begin match Infer.check_sort_noexn p [] a with
| None -> fatal pos "%a@ cannot be typed by a sort" term a
| Some (a,_) ->
let t =
match t with
| None -> None
| Some {elt=t;pos} ->
match Infer.check_noexn p [] t a with
| None ->
fatal pos "%a@ cannot be of type@ %a" term t term a
| Some t -> Some (Pos.make pos t)
in
(t, a)
end
| None ->
match t with
| None -> assert false
| Some {elt=t;pos} ->
match Infer.infer_noexn p [] t with
| None -> fatal pos "%a@ is not typable" term t
| Some (t,a) -> Some (Pos.make pos t), a
in
let pdata_proof, pe =
match p_sym_prf with
| None -> [], Pos.make (Pos.end_pos pos) P_proof_end
| Some (ts, pe) -> ts, pe
in
let declpos = Pos.cat pos (Option.bind p_sym_typ (fun x -> x.pos)) in
let pdata_finalize ss ps =
match pe.elt with
| P_proof_abort -> wrn pe.pos "Proof aborted."; ss
| P_proof_admitted ->
if finished ps then
fatal pe.pos "The proof is finished. Use 'end' instead.";
let admit_goal g =
match g with
| Unif _ -> fatal pos "Cannot admit unification goals."
| Typ gt ->
let m = gt.goal_meta in
match !(m.meta_value) with
| None -> Tactic.admit_meta ss p_sym_nam.pos m
| Some _ -> ()
in
List.iter admit_goal ps.proof_goals;
Console.out 2 (Color.red "symbol %a : %a") uid id term a;
wrn pe.pos "Proof admitted.";
let d =
if opaq then None else
Option.map (fun m -> unfold (mk_Meta(m,[||]))) ps.proof_term
in
fst (Sig_state.add_symbol
ss expo prop mstrat opaq p_sym_nam declpos a impl d)
| P_proof_end ->
if not (finished ps) then
fatal pe.pos "The proof is not finished:@.%a" goals ps;
let d =
if opaq then None else
Option.map (fun m -> unfold (mk_Meta(m,[||]))) ps.proof_term
in
Console.out 2 (Color.red "symbol %a : %a") uid id term a;
fst (Sig_state.add_symbol
ss expo prop mstrat opaq p_sym_nam declpos a impl d)
in
let pdata_state =
let proof_goals = Proof.add_goals_of_problem p [] in
if p_sym_def then
let m = LibMeta.fresh p a 0 in
let g = Goal.of_meta m in
let ps = {proof_name = p_sym_nam; proof_term = Some m;
proof_goals = g :: proof_goals} in
match pt, t with
| Some pt, Some t ->
let gt = match g with Typ gt -> gt | _ -> assert false in
Tactic.tac_refine ~check:false pt.pos ps gt proof_goals p t.elt
| _, _ -> Tactic.tac_solve pos ps
else
let ps = {proof_name = p_sym_nam; proof_term = None; proof_goals} in
Tactic.tac_solve pos ps
in
if p_sym_prf = None && not (finished pdata_state) then wrn pos
"Some metavariables could not be solved: a proof must be given";
{ pdata_sym_pos=p_sym_nam.pos; pdata_state; pdata_proof
; pdata_finalize; pdata_end_pos=pe.pos; pdata_prv }
in
(ss, Some pdata, None)
(** [too_long] indicates the duration after which a warning should be given to
indicate commands that take too long to execute. *)
let too_long = Stdlib.ref infinity
(** [get_proof_data compile ss cmd] adds to the previous [command] some
exception handling. In particular, the position of [cmd] is used on errors
that lack a specific position. All exceptions except [Timeout] and [Fatal]
are captured, although they should not occur. *)
let get_proof_data : compiler -> sig_state -> p_command -> cmd_output =
fun compile ss ({pos;_} as cmd) ->
sig_state := ss;
try
let (tm, ss) = Extra.time (get_proof_data compile ss) cmd in
if Stdlib.(tm >= !too_long) then
wrn pos "It took %.2f seconds to handle the command." tm;
ss
with
| Timeout as e -> raise e
| Fatal(Some(Some(_)),_) as e -> raise e
| Fatal(None ,m) -> fatal pos "Error on command.@.%s" m
| Fatal(Some(None) ,m) -> fatal pos "Error on command.@.%s" m
| e ->
fatal pos "Uncaught exception: %s." (Printexc.to_string e)
(** [handle compile_mod ss cmd] retrieves proof data from [cmd] (with
{!val:get_proof_data}) and handles proofs using functions from
{!module:Tactic} The function [compile_mod] is used to compile required
modules recursively. *)
let handle : compiler -> Sig_state.t -> Syntax.p_command -> Sig_state.t =
fun compile_mod ss cmd ->
LibMeta.reset_meta_counter ();
let (ss, p, _) = get_proof_data compile_mod ss cmd in
match p with
| None -> ss
| Some d ->
let ps, _ =
fold_proof (Tactic.handle ss d.pdata_sym_pos d.pdata_prv)
(d.pdata_state, None) d.pdata_proof
in d.pdata_finalize ss ps