This repository has been archived by the owner on Dec 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.ml
134 lines (113 loc) · 3.88 KB
/
common.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
(** The obligatory utilities-needed-by-everything module. *)
let _debug = ref false
let debug_print s =
if !_debug then print_endline s
else ()
(** Utility function to find index of an item in a list *)
let listIndex_opt es e =
let rec loop es i =
match es with
| [] -> None
| elt::rest ->
if elt = e then (Some i)
else loop rest (i+1)
in
loop es 0
(** array find. There is something like this in 5.1 but this will do. *)
let array_find_index_ex a indf =
let rec loop i =
if i = Array.length a then raise Not_found
else (
let ai = Array.get a i in
if indf ai then (i, ai)
else loop (i+1)
)
in (loop 0)
(** in-place type variables for generics, with signature impl requirements *)
(* wait, should this go in types.ml? *)
(* This screws up all my types when it's an alias for string *)
(* type typevar = string (\* { *)
(* varname: string; *)
(* impls: string list (\* probably should be a set later. *\) *)
(* } *\) *)
module StrMap = Map.Make(String)
module StrSet = Set.Make(String)
module StrPairs =
struct
type t = string * string
let compare (x0,y0) (x1,y1) =
match Stdlib.compare x0 x1 with
0 -> Stdlib.compare y0 y1
| c -> c
end
(** Map from string pairs. Currently only used for (module, classname)
types in the tenv. *)
module PairMap = Map.Make(StrPairs)
let print_typekeys (tmap: 'a PairMap.t) =
PairMap.bindings tmap
|> List.iter (fun ((modalias, tname), _) ->
print_endline (modalias ^ " :: " ^ tname))
(** position info to decorate the AST with. TODO: don't put it here. *)
type locinfo = Lexing.position * Lexing.position
(** This is still used for error messages. And importStmt! *)
type 'a located =
{ loc: Lexing.position * Lexing.position; value: 'a }
(** Format two Lexing.location objects as a string showing the range. *)
(* Maybe put this in a common thing too. *)
let format_loc (spos: Lexing.position) (epos: Lexing.position) =
if spos.pos_lnum = epos.pos_lnum then
Format.sprintf "%d:%d-%d"
spos.pos_lnum
(spos.pos_cnum - spos.pos_bol)
(epos.pos_cnum - epos.pos_bol)
else
Format.sprintf "%d:%d-%d:%d"
spos.pos_lnum
(spos.pos_cnum - spos.pos_bol)
epos.pos_lnum
(epos.pos_cnum - epos.pos_bol)
(** Generate string buffer showing a sequence of errors. *)
(* Is this only used here at the top level? Should it go in common? *)
let format_errors (elist: string located list) =
let format1 {loc; value} =
(* TODO: distinguish between error and warning. *)
"Error: " ^ (fst loc).pos_fname ^ " " ^ format_loc (fst loc) (snd loc)
^ ":\n " ^ value
in
(* errors append at beginning, so need to reverse the list. *)
let errstrs = List.rev_map format1 elist in
String.concat "\n" errstrs ^ "\n"
(* List.concat_map doesn't exist until OCaml 4.10 *)
let concat_map f l = List.concat (List.map f l)
(** Mash list of error lists into a single list *)
let concat_errors rlist =
(* the list of errors are each themselves lists. *)
List.concat (
concat_map (
fun r -> match r with
| Ok _ -> []
| Error erec -> [erec]
) rlist
)
(** Combine all OKs into a single list *)
let concat_ok rlist = concat_map Result.to_list rlist
(* TODO: a check_list that does the map and concat error/Ok *)
(** This might replace most concat_errors and concat_ok *)
let unzip_results rlist =
(* the list of errors are each themselves lists. *)
let errs = List.concat (
concat_map (
fun r -> match r with
| Ok _ -> []
| Error erec -> [erec]
) rlist
)
in
(concat_map Result.to_list rlist, errs)
(** Fold over a list with a function that returns a result *)
let rec fold_list_result f blist res =
match blist with
| [] -> res
| b::bs -> (match (f b res) with
| Ok rnew -> fold_list_result f bs rnew
| Error e -> Error e)