Skip to content

Commit 7f78a6f

Browse files
committed
coqtop peek in coqloop code not clexer
Fix incorrect locations when end of line spaces aren't stripped
1 parent 68e5ecc commit 7f78a6f

File tree

6 files changed

+40
-18
lines changed

6 files changed

+40
-18
lines changed

.gitattributes

+5
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,13 @@ dune* whitespace=blank-at-eol,tab-in-indent
5656
.gitattributes whitespace=blank-at-eol,tab-in-indent
5757
_CoqProject whitespace=blank-at-eol,tab-in-indent
5858
Dockerfile whitespace=blank-at-eol,tab-in-indent
59+
60+
# multiple newlines at the end
5961
00000-title.rst -whitespace
6062

63+
# tests location correctness with trailing whitespace
64+
/test-suite/output-coqtop/BracketLoc.v -whitespace
65+
6166
# tabs are allowed in Makefiles.
6267
Makefile* whitespace=blank-at-eol
6368
tools/CoqMakefile.in whitespace=blank-at-eol

parsing/cLexer.ml

+1-5
Original file line numberDiff line numberDiff line change
@@ -723,11 +723,7 @@ let rec next_token ~diff_mode ttree loc s =
723723
Stream.junk () s;
724724
let ep = Stream.count s in
725725
let t,new_between_commands =
726-
if !between_commands then begin
727-
(* peek to force reading a following newline, cf #19355 *)
728-
let _ = Stream.peek () s in
729-
(KEYWORD (String.make 1 c), set_loc_pos loc bp ep), true
730-
end
726+
if !between_commands then (KEYWORD (String.make 1 c), set_loc_pos loc bp ep), true
731727
else process_chars ~diff_mode ttree loc bp [c] s, false
732728
in
733729
between_commands := new_between_commands; t

test-suite/output-coqtop/BracketLoc.out

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Coq < 1 goal
44
============================
55
True
66

7+
Toplevel input, characters 11-12:
8+
> Goal True. }
9+
> ^
10+
Error: The proof is not focused
11+
712
Unnamed_thm < Toplevel input, characters 2-3:
813
> }
914
> ^

test-suite/output-coqtop/BracketLoc.v

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Goal True.
2-
}
1+
Goal True. }
2+
}
33
}
44
exact 0.

toplevel/coqloop.ml

+26-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type input_buffer = {
2323
mutable str : Bytes.t; (* buffer of already read characters *)
2424
mutable len : int; (* number of chars in the buffer *)
2525
mutable bols : int list; (* offsets in str of beginning of lines *)
26+
mutable stream : (unit,char) Gramlib.Stream.t; (* stream of chars *)
2627
mutable tokens : Pcoq.Parsable.t; (* stream of tokens *)
2728
mutable start : int } (* stream count of the first char of the buffer *)
2829

@@ -33,10 +34,23 @@ let resize_buffer ibuf = let open Bytes in
3334
blit ibuf.str 0 nstr 0 (length ibuf.str);
3435
ibuf.str <- nstr
3536

37+
let peek_to_newline ibuf =
38+
(* peek to see a newline following the latest command
39+
cf #19355 *)
40+
let rec aux n =
41+
let l = Gramlib.Stream.npeek () n ibuf.stream in
42+
if List.length l < n then ()
43+
else match CList.last l with
44+
| '\n' -> ()
45+
| ' ' | '\t' -> aux (n+1)
46+
| _ -> (* nonblank character: the latest command is not the last on this line *) ()
47+
in
48+
aux 1
49+
3650
(* Delete all irrelevant lines of the input buffer. Keep the last line
3751
in the buffer (useful when there are several commands on the same line). *)
38-
3952
let resynch_buffer ibuf =
53+
let () = peek_to_newline ibuf in
4054
match ibuf.bols with
4155
| ll::_ ->
4256
let new_len = ibuf.len - ll in
@@ -90,7 +104,11 @@ let get_bols_of_loc ibuf (bp,ep) =
90104
let nafter = if ll < ep then add_line (ll,ba) after else after in
91105
lines_rec ll nafter fl
92106
in
93-
let (fl,ll) = lines_rec ibuf.len ([],None) ibuf.bols in
107+
let bols = match ibuf.bols with
108+
| [] -> [ibuf.len+1] (* no newline at the end of the command, pretend there was one *)
109+
| _ :: _ as bols -> bols
110+
in
111+
let (fl,ll) = lines_rec ibuf.len ([],None) bols in
94112
(fl,Option.get ll)
95113

96114
let dotted_location (b,e) =
@@ -217,19 +235,23 @@ let top_buffer =
217235
^ make_emacs_prompt doc
218236
^ emacs_prompt_endstring()
219237
in
238+
let stream = Gramlib.Stream.empty () in
220239
{ prompt = pr;
221240
str = Bytes.empty;
222241
len = 0;
223242
bols = [];
224-
tokens = Pcoq.Parsable.make (Gramlib.Stream.empty ());
243+
stream;
244+
tokens = Pcoq.Parsable.make stream;
225245
start = 0 }
226246

227247
(* Intialize or reinitialize the char stream *)
228248
let reset_input_buffer ~state =
249+
let stream = Gramlib.Stream.from (prompt_char state.Vernac.State.doc stdin top_buffer) in
229250
top_buffer.str <- Bytes.empty;
230251
top_buffer.len <- 0;
231252
top_buffer.bols <- [];
232-
top_buffer.tokens <- Pcoq.Parsable.make (Gramlib.Stream.from (prompt_char state.Vernac.State.doc stdin top_buffer));
253+
top_buffer.stream <- stream;
254+
top_buffer.tokens <- Pcoq.Parsable.make stream;
233255
top_buffer.start <- 0
234256

235257
let set_prompt prompt =

toplevel/coqloop.mli

+1-7
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,7 @@
1313
(** A buffer for the character read from a channel. We store the command
1414
* entered to be able to report errors without pretty-printing. *)
1515

16-
type input_buffer = {
17-
mutable prompt : Stm.doc -> string;
18-
mutable str : Bytes.t; (** buffer of already read characters *)
19-
mutable len : int; (** number of chars in the buffer *)
20-
mutable bols : int list; (** offsets in str of beginning of lines *)
21-
mutable tokens : Pcoq.Parsable.t; (** stream of tokens *)
22-
mutable start : int } (** stream count of the first char of the buffer *)
16+
type input_buffer
2317

2418
(** The input buffer of stdin. *)
2519

0 commit comments

Comments
 (0)