-
Notifications
You must be signed in to change notification settings - Fork 0
/
pos.ml
128 lines (109 loc) · 3.82 KB
/
pos.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
(**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the "hack" directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*)
open Lexing
open Utils
(* Note: While Pos.string prints out positions as closed intervals, pos_start
* and pos_end actually form a half-open interval (i.e. pos_end points to the
* character *after* the last character of the relevant lexeme.) *)
type 'a pos = {
pos_file: 'a [@opaque];
pos_start: Lexing.position [@opaque];
pos_end: Lexing.position [@opaque];
}
[@@deriving show]
type t = Relative_path.t pos [@opaque]
[@@deriving show]
type absolute = string pos
let none = {
pos_file = Relative_path.default ;
pos_start = dummy_pos ;
pos_end = dummy_pos ;
}
let filename p = p.pos_file
let info_pos t =
let line = t.pos_start.pos_lnum in
let start = t.pos_start.pos_cnum - t.pos_start.pos_bol + 1 in
let end_ = t.pos_end.pos_cnum - t.pos_start.pos_bol in
line, start, end_
let info_raw t = t.pos_start.pos_cnum, t.pos_end.pos_cnum
let length t = t.pos_end.pos_cnum - t.pos_start.pos_cnum
let string t =
let line, start, end_ = info_pos t in
Printf.sprintf "File %S, line %d, characters %d-%d:"
t.pos_file line start end_
let json pos =
let line, start, end_ = info_pos pos in
let fn = filename pos in
Hh_json.JAssoc [
"filename", Hh_json.JString fn;
"line", Hh_json.JInt line;
"char_start", Hh_json.JInt start;
"char_end", Hh_json.JInt end_;
]
let inside p line char_pos =
let first_line = p.pos_start.pos_lnum in
let last_line = p.pos_end.pos_lnum in
if first_line = last_line then
let _, start, end_ = info_pos p in
first_line = line && start <= char_pos && char_pos <= end_
else
if line = first_line then char_pos > (p.pos_start.pos_cnum - p.pos_start.pos_bol)
else if line = last_line then char_pos <= (p.pos_end.pos_cnum - p.pos_end.pos_bol)
else line > first_line && line < last_line
let contains pos_container pos =
filename pos_container = filename pos &&
pos.pos_start.pos_cnum >= pos_container.pos_start.pos_cnum &&
pos.pos_end.pos_cnum <= pos_container.pos_end.pos_cnum
let make file (lb:Lexing.lexbuf) =
let pos_start = lexeme_start_p lb in
let pos_end = lexeme_end_p lb in
{ pos_file = file;
pos_start = pos_start;
pos_end = pos_end;
}
let make_from file =
let pos = Lexing.dummy_pos in
{ pos_file = file;
pos_start = pos;
pos_end = pos;
}
let btw x1 x2 =
if x1.pos_file <> x2.pos_file
then failwith "Position in separate files" ;
if x1.pos_end > x2.pos_end
then failwith "Invalid positions Pos.btw" ;
{ x1 with pos_end = x2.pos_end }
let set_line pos value =
let pos_start = pos.pos_start in
let pos_end = pos.pos_end in
let pos_start = { pos_start with pos_lnum = value } in
let pos_end = { pos_end with pos_lnum = value } in
{ pos with pos_start; pos_end }
let to_absolute p = { p with pos_file = Relative_path.to_absolute (p.pos_file) }
(* Compare by filename, then tie-break by start position, and finally by the
* end position *)
let compare x y =
let rec seq = function
| [] -> 0
| f :: rl ->
let result = f x y in
if result <> 0 then result else seq rl
in
seq [(fun x y -> compare x.pos_file y.pos_file);
(fun x y -> compare x.pos_start.pos_lnum y.pos_start.pos_lnum);
(fun x y -> compare x.pos_start.pos_cnum y.pos_start.pos_cnum);
(fun x y -> compare x.pos_end.pos_cnum y.pos_end.pos_cnum)]
module Map = MyMap (struct
type path = t
(* The definition below needs to refer to the t in the outer scope, but MyMap
* expects a module with a type of name t, so we define t in a second step *)
type t = path
let compare = compare
end)