Skip to content

Commit 109094e

Browse files
authored
fix virtual positions for symbols and rules generated by inductive (#1448)
- fix Pos.pos_end by setting start_offset properly - remove Pos.before (unused) - unfold Pos.after to Pos.shift 1 to easily localize all the uses of shift - Tactic.p_term_of_string_term: fix initial buffer position using pos_of_string - rename Lcr.shift into Lcr.reindex to avoid confusion with Pos.shift
1 parent 3a1bf4f commit 109094e

8 files changed

Lines changed: 59 additions & 53 deletions

File tree

src/common/pos.ml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ let equal : popt -> popt -> bool = fun p1 p2 ->
101101
let pos_end : popt -> popt = fun po ->
102102
match po with
103103
| None -> None
104-
| Some p -> Some {p with start_line = p.end_line; start_col = p.end_col}
104+
| Some p -> Some {p with start_offset=p.end_offset
105+
; start_line = p.end_line; start_col = p.end_col}
105106

106107
(** [cat] extends and hide the above [cat] function from [pos] to [popt]. *)
107108
let cat : popt -> popt -> popt = fun p1 p2 ->
@@ -111,15 +112,14 @@ let cat : popt -> popt -> popt = fun p1 p2 ->
111112
| None, Some p -> Some p
112113
| None, None -> None
113114

114-
(** [shift k p] returns a position that is [k] characters after [p]. *)
115+
(** [shift k p] returns a position that is [k] characters after [p].
116+
/!\ The generated position may not actually exist in the user input.
117+
The fields start_offset, end_offset and end_col are inconsistent. *)
115118
let shift : int -> popt -> popt = fun k p ->
116119
match p with
117120
| None -> assert false
118121
| Some ({start_col; _} as p) -> Some {p with start_col = start_col + k}
119122

120-
let after = shift 1
121-
let before = shift (-1)
122-
123123
(** [lexing_opt p] converts a [popt] into a [Lexing.position]. *)
124124
let lexing_opt (p:popt): Lexing.position =
125125
match p with

src/core/term.ml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,12 @@ and sym =
200200
the same time a definition (i.e., {!field:sym_def} different from [None])
201201
and rewriting rules (i.e., {!field:sym_rules} is non-empty). *)
202202

203-
(** {b NOTE} For generated symbols (recursors, axioms), {!field:sym_pos} may
204-
not be valid positions in the source. These virtual positions are however
205-
important for exporting lambdapi files to other formats. *)
203+
(** {b NOTE} For generated symbols (axioms, inductive types, constructors,
204+
recursors), {!field:sym_decl_pos} may not be an actual position in the
205+
source. These virtual positions are used to order symbol and rule
206+
declarations when exporting a signature. They should NOT be used as
207+
references to user source files. This field may be removed in the
208+
future. *)
206209

207210
(** {3 Representation of rewriting rules} *)
208211

src/export/dk.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ type decl =
8888
| Sym of sym
8989
| Rule of (Path.t * string * rule)
9090

91-
(** Declarations are ordered wrt their positions in the source. *)
91+
(** Declarations are ordered wrt their declaration positions. *)
9292

9393
let pos_of_decl : decl -> Pos.popt = fun i ->
9494
match i with
95-
| Sym s -> s.sym_pos
95+
| Sym s -> s.sym_decl_pos
9696
| Rule (_,_,r) -> r.rule_pos
9797

9898
let cmp : decl cmp = cmp_map (Lplib.Option.cmp Pos.cmp) pos_of_decl

src/handle/command.ml

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,11 @@ let handle_modifiers :
178178
in
179179
(prop, expo, strat, opaq)
180180

181-
(** [handle_inductive_symbol ss e p strat x xs a] handles the command
182-
[e p strat symbol x xs : a] with [ss] as the signature state.
183-
The command is at position [pos].
184-
On success, an updated signature state and the new symbol are returned. *)
181+
(** [handle_inductive_symbol ss expo prop strat id declpos xs a] handles the
182+
command [expo prop strat symbol id xs : a] with [ss] as the signature
183+
state. /!\ Use [declpos] as its position (used in commands exporting
184+
signatures). On success, an updated signature state and the new symbol are
185+
returned. *)
185186
let handle_inductive_symbol : sig_state -> expo -> prop -> match_strat
186187
-> p_ident -> popt -> p_params list -> p_term -> sig_state * sym =
187188
fun ss expo prop mstrat ({elt=name;pos} as id) declpos xs typ ->
@@ -354,12 +355,9 @@ let get_proof_data : compiler -> sig_state -> p_command -> cmd_output =
354355
inductive types.";
355356
if opaq then
356357
fatal pos "Inductive types cannot be declared opaque.";
357-
(* Add inductive types in the signature. *)
358+
(* Add inductive types in the signature, all at position [pos]. *)
358359
let add_ind_sym (ss, ind_sym_list) {elt=(id,pt,_); _} =
359360
let (ss, ind_sym) =
360-
(* All inductive types are declared at position [pos]
361-
so that constructors are declared afterwards. *)
362-
let id = {id with pos} in
363361
handle_inductive_symbol ss expo Const Eager id pos params pt in
364362
(ss, ind_sym::ind_sym_list)
365363
in
@@ -369,13 +367,13 @@ let get_proof_data : compiler -> sig_state -> p_command -> cmd_output =
369367
let params =
370368
List.map (fun (idopts,typopt,_) -> (idopts,typopt,true)) params in
371369
(* Add constructors in the signature. *)
370+
let cons_pos = shift 1 pos in (* after types *)
372371
let add_constructors
373372
(ss, cons_sym_list_list) {elt=(_,_,p_cons_list); _} =
374373
let add_cons_sym (ss, cons_sym_list) (id, pt) =
375374
let (ss, cons_sym) =
376-
handle_inductive_symbol ss expo Const Eager id pos
377-
params pt in
378-
(ss, cons_sym::cons_sym_list)
375+
handle_inductive_symbol ss expo Const Eager id cons_pos params pt
376+
in (ss, cons_sym::cons_sym_list)
379377
in
380378
let (ss, cons_sym_list_rev) =
381379
List.fold_left add_cons_sym (ss, []) p_cons_list in
@@ -406,19 +404,19 @@ let get_proof_data : compiler -> sig_state -> p_command -> cmd_output =
406404
Inductive.gen_rec_types cfg pos ind_list vs env ind_pred_map x_str
407405
in
408406
(* Add the induction principles in the signature. *)
407+
let rec_pos = shift 2 pos in (* after types and constructors *)
409408
let add_recursor (ss, rec_sym_list) ind_sym rec_typ =
410409
let rec_name = Inductive.rec_name ind_sym in
411410
if Sign.mem ss.signature rec_name then
412411
fatal pos "Symbol %a already exists." uid rec_name;
413412
let (ss, rec_sym) =
414413
Console.out 2 (Color.gre "symbol %a : %a")
415414
uid rec_name term rec_typ;
416-
(* Recursors are declared after the types and constructors. *)
417-
let pos = after (pos_end pos) in
415+
(* Add recursors in the signature, all at position [shift 2 pos]. *)
418416
let id = Pos.make pos rec_name in
419417
let r =
420-
Sig_state.add_symbol ss expo Defin Eager false id
421-
None rec_typ [] None
418+
Sig_state.add_symbol ss expo Defin Eager false id rec_pos
419+
rec_typ [] None
422420
in sig_state := fst r; r
423421
in
424422
(ss, rec_sym::rec_sym_list)

src/handle/inductive.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,6 @@ let iter_rec_rules :
294294
popt -> inductive -> var array -> ind_pred_map
295295
-> (p_rule -> unit) -> unit =
296296
fun pos ind_list vs ind_pred_map f ->
297-
(* Rules are declared after recursor declarations. *)
298-
let rules_pos = shift (List.length ind_list + 1) (pos_end pos) in
299297
let n = Array.length vs in
300298

301299
(* variable name used for a recursor case argument *)
@@ -325,6 +323,8 @@ let iter_rec_rules :
325323
P.appl (P.appl_wild head (List.length ts - n)) t
326324
in
327325

326+
let rule_pos = shift 3 pos in (* after types, constructors and recursors *)
327+
328328
(* [gen_rule_cons ind_sym rec_sym cons_sym] generates the p_rule of the
329329
recursor [rec_sym] of the inductive type [ind_sym] for the constructor
330330
[cons_sym]. *)
@@ -347,7 +347,7 @@ let iter_rec_rules :
347347
let nonrec_dom _ _ next = next in
348348
let codom xs rhs _ ts =
349349
let cons_arg = P.appl_list (P.iden cons_sym.sym_name) (List.rev xs) in
350-
Pos.make rules_pos (arec ind_sym ts cons_arg, rhs)
350+
Pos.make rule_pos (arec ind_sym ts cons_arg, rhs)
351351
in
352352
fold_cons_type pos ind_pred_map "" ind_sym vs cons_sym inj_var
353353
init aux acc_rec_dom rec_dom acc_nonrec_dom nonrec_dom codom

src/handle/tactic.ml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,14 @@ let add_axiom : Sig_state.t -> popt -> meta -> sym =
3434
let sym =
3535
wrn sym_pos "axiom %a: %a" uid name term !(m.meta_type);
3636
(* Temporary hack for axioms to have a declaration position in the order
37-
they are created. *)
37+
they are created, and strictly before the symbol. *)
38+
(* FIXME: use sym_decl_pos instead ? *)
39+
let id = {elt=name; pos=sym_pos} in
3840
let pos = shift Stdlib.(!admitted) sym_pos in
39-
let id = Pos.make pos name in
4041
(* We ignore the new ss returned by Sig_state.add_symbol: axioms do not
4142
need to be in scope. *)
4243
snd (Sig_state.add_symbol ss
43-
Public Defin Eager true id None !(m.meta_type) [] None)
44+
Public Defin Eager true id pos !(m.meta_type) [] None)
4445
in
4546
(* Create the value which will be substituted for the metavariable. This
4647
value is [sym x0 ... xn] where [xi] are variables that will be
@@ -304,14 +305,21 @@ let p_ident_of_var (pos:popt) (t:term) :p_ident =
304305
| Vari v -> Pos.make pos (base_name v)
305306
| _ -> fatal pos "Not a variable of the proof context: %a." term t
306307

308+
(* [pos_of_string s] assumes that [s] is a string literal and returns the
309+
lexing position of the content of [s]. *)
310+
let pos_of_string: sym -> Lexing.position =
311+
let f p = {p with start_offset=p.start_offset+1; start_col=p.start_col+1;
312+
end_offset=p.end_offset-1; end_col=p.end_col-1} in
313+
fun s -> lexing_opt (Option.map f s.sym_pos)
314+
307315
(** [p_term_of_string_term pos t] turns into a p_term a string literal term
308316
[t] that is part of a bigger term obtained by scoping and normalizing of a
309317
p_term at position [pos]. *)
310318
let p_term_of_string_term (pos:popt) (t:term): p_term =
311319
match t with
312320
| Symb s when String.is_string_literal s.sym_name ->
313-
let p = lexing_opt (after s.sym_pos) in
314-
Parsing.Parser.Lp.parse_term_string p (String.remove_quotes s.sym_name)
321+
Parsing.Parser.Lp.parse_term_string (pos_of_string s)
322+
(String.remove_quotes s.sym_name)
315323
| _ -> fatal pos "not a string literal"
316324

317325
(** [p_rwpatt_of_string_term pos t] turns into a p_rwpatt option a string
@@ -323,9 +331,8 @@ let p_rwpatt_of_string_term (pos:popt) (t:term): p_rwpatt option =
323331
match t with
324332
| Symb s when String.is_string_literal s.sym_name ->
325333
let string = String.remove_quotes s.sym_name in
326-
if string = "" then None
327-
else let p = lexing_opt (after s.sym_pos) in
328-
Some (Parsing.Parser.Lp.parse_rwpatt_string p string)
334+
if string = "" then None else
335+
Some (Parsing.Parser.Lp.parse_rwpatt_string (pos_of_string s) string)
329336
| _ -> fatal pos "not a string literal"
330337

331338
(** [int_of_term pos t] returns the int contained in a string literal

src/parsing/parser.ml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ sig
160160
set_filename lb lexpos.pos_fname;
161161
Stream.next (parse_lexbuf' ~allow_rocq_syntax None entry lb)
162162

163-
164163
(* exported functions *)
165164
let parse_term_string =
166165
parse_entry_string ~allow_rocq_syntax:false LpParser.term
@@ -193,7 +192,6 @@ let path_of_string : string -> Path.t = fun s ->
193192
LpLexer.SyntaxError _ ->
194193
fatal_no_pos "Syntax error: \"%s\" is not a path." s
195194

196-
197195
(** [qident_of_string s] converts the string [s] into a qident. *)
198196
let qident_of_string : string -> Core.Term.qident = fun s ->
199197
let lb = Utf8.from_string s in

src/tool/lcr.ml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ Warning: we currently do not take into account the rules having higher-order
2121
2222
Remark: When trying to unify a subterm of a rule LHS with the LHS of another
2323
rule, we need to rename the pattern variables of one of the LHS to avoid
24-
name clashes. To this end, we use the [shift] function below which replaces
25-
[Patt(i,n,_)] by [Patt(-i-1,n ^ "'",_)]. The printing function [subs] below
26-
takes this into account. *)
24+
name clashes. To this end, we use the [reindex] function below which
25+
replaces [Patt(i,n,_)] by [Patt(-i-1,n ^ "'",_)]. The printing function
26+
[subs] below takes this into account. *)
2727

2828
open Core open Term open Print
2929
open Timed
@@ -99,8 +99,8 @@ let occurs : int -> term -> bool = fun i ->
9999
| LLet _ -> assert false
100100
in occ
101101

102-
(** [shift t] replaces in [t] every pattern index i by -i-1. *)
103-
let rec shift : term -> term = fun t ->
102+
(** [reindex t] replaces in [t] every pattern index i by -i-1. *)
103+
let rec reindex : term -> term = fun t ->
104104
match unfold t with
105105
| Vari _
106106
| Type
@@ -109,16 +109,16 @@ let rec shift : term -> term = fun t ->
109109
| Wild
110110
| Plac _
111111
| TRef _ -> t
112-
| Prod(a,b) -> mk_Prod (shift a, shift_binder b)
113-
| Abst(a,b) -> mk_Abst (shift a, shift_binder b)
114-
| Appl(a,b) -> mk_Appl (shift a, shift b)
115-
| Meta(m,ts) -> mk_Meta (m, Array.map shift ts)
112+
| Prod(a,b) -> mk_Prod (reindex a, reindex_binder b)
113+
| Abst(a,b) -> mk_Abst (reindex a, reindex_binder b)
114+
| Appl(a,b) -> mk_Appl (reindex a, reindex b)
115+
| Meta(m,ts) -> mk_Meta (m, Array.map reindex ts)
116116
| Patt(None,_,_) -> assert false
117-
| Patt(Some i,n,ts) -> mk_Patt (Some(-i-1), n ^ "'", Array.map shift ts)
117+
| Patt(Some i,n,ts) -> mk_Patt (Some(-i-1), n ^ "'", Array.map reindex ts)
118118
| Bvar _ -> assert false
119-
| LLet(a,t,b) -> mk_LLet (shift a, shift t, shift_binder b)
120-
and shift_binder b =
121-
let x, t = unbind b in bind_var x (shift t)
119+
| LLet(a,t,b) -> mk_LLet (reindex a, reindex t, reindex_binder b)
120+
and reindex_binder b =
121+
let x, t = unbind b in bind_var x (reindex t)
122122

123123
(** Type for pattern variable substitutions. *)
124124
type subs = term IntMap.t
@@ -372,7 +372,7 @@ let iter_cps_with_rule :
372372
(*if Logger.log_enabled() then
373373
log_cp "iter_cps_with_rule@.%a@.%a" Print.rule lr Print.rule gd;*)
374374
let l = lhs lr and r = rhs lr and g = lhs gd and d = rhs gd in
375-
let l = shift l and r = shift r in
375+
let l = reindex l and r = reindex r in
376376
let i = id_sym_rule lr and j = id_sym_rule gd in
377377
let f _ p l_p = cp_cand_fun h pos i l r p l_p j g d in
378378
iter_subterms pos f l
@@ -555,7 +555,7 @@ let check_cps_subterms_eq : Pos.popt -> sym_rule -> unit =
555555
if Logger.log_enabled() then log_cp "check_cps_subterms_eq";
556556
(*if Logger.log_enabled() then
557557
log_cp "check_cps_subterms_eq@.%a@.%a" Print.rule lr Print.rule gd;*)
558-
let l = shift (lhs lr) and r = shift (rhs lr) in
558+
let l = reindex (lhs lr) and r = reindex (rhs lr) in
559559
let i = id_sym_rule lr in
560560
let f s p l_p =
561561
match !(s.sym_def) with

0 commit comments

Comments
 (0)