-
Notifications
You must be signed in to change notification settings - Fork 0
/
ast_transformer.ml
97 lines (93 loc) · 2.96 KB
/
ast_transformer.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
open Core
open Generic_types
(* returns total bounds of the current item *)
let bounds_iterator () =
let min_position = ref None in
let max_position = ref None in
let retrieve_bounds () = Option.value_exn !min_position, Option.value_exn !max_position in
let update_bounds pstr_loc =
let open Lexing in
let open Location in
let () =
let start_cnum = min pstr_loc.loc_end.pos_cnum pstr_loc.loc_start.pos_cnum in
let min_cnum = match !min_position with
None -> start_cnum
| Some v -> v in
if start_cnum = -1 then ()
else min_position := Some (min min_cnum start_cnum)
in
let () =
let end_cnum = max pstr_loc.loc_end.pos_cnum pstr_loc.loc_start.pos_cnum in
let max_cnum = match !max_position with
None -> end_cnum
| Some v -> v in
if end_cnum = -1 then ()
else max_position := Some (max max_cnum end_cnum)
in
()
in
Ast_iterator.{
default_iterator
with
location = fun _ -> update_bounds
}, retrieve_bounds
let complete_bounds_iterator () =
let min_col_position = ref (-1) in
let max_col_position = ref (-1) in
let min_line_position = ref (-1) in
let max_line_position = ref (-1) in
let cmp f a b = match (a,b) with
| -1, -1 -> -1
| -1, b -> b
| a, -1 -> a
| a, b -> f a b in
let min = cmp min in
let max = cmp max in
let retrieve_bounds () =
(!min_line_position, !min_col_position),
(!max_line_position, !max_col_position)
in
let update_bounds pstr_loc =
let open Lexing in
let open Location in
let () =
min_col_position := min !min_col_position pstr_loc.loc_start.pos_cnum;
min_line_position := min !min_line_position pstr_loc.loc_start.pos_lnum;
max_col_position := max !max_col_position pstr_loc.loc_end.pos_cnum;
max_line_position := max !max_line_position pstr_loc.loc_end.pos_lnum;
in
()
in
Ast_iterator.{
default_iterator
with
location = fun _ -> update_bounds
}, retrieve_bounds
(* returns the nearest enclosing bounds to a point *)
let enclosing_bounds_iterator point () =
let bounds = ref None in
let retrieve_bounds () = !bounds in
let within_bounds st ed point = st <= point && point <= ed in
let encloses (st,ed) (st',ed') =
within_bounds st ed st' && within_bounds st ed ed' in
let smaller (st,ed) (st',ed') =
ed - st <= st' - ed' in
(* given two regions enclosing point, returns the smaller one*)
let choose (st,ed) (st',ed') =
if encloses (st,ed) (st',ed') || smaller (st',ed') (st,ed)
then (st',ed')
else (st,ed) in
let update_bounds ({
loc_start={ pos_cnum=st;_ };
loc_end={pos_cnum=ed;_}; _
}: Location.t) =
if within_bounds st ed point then
match !bounds with
| None -> bounds := Some (st,ed)
| Some (st',ed') -> bounds := Some (choose (st,ed) (st',ed'))
else () in
Ast_iterator.{
default_iterator
with
location = fun _ -> update_bounds
},retrieve_bounds