1
+ open SharedTypes
2
+ (* This is intended to be a debug tool. It's by no means complete. Rather, you're encouraged to extend this with printing whatever types you need printing. *)
3
+
4
+ let emptyLocDenom = " <x>"
5
+ let hasCursorDenom = " <*>"
6
+ let noCursorDenom = " "
7
+
8
+ let printLocDenominator loc ~pos =
9
+ match loc |> CursorPosition. classifyLoc ~pos with
10
+ | EmptyLoc -> emptyLocDenom
11
+ | HasCursor -> hasCursorDenom
12
+ | NoCursor -> noCursorDenom
13
+
14
+ let printLocDenominatorLoc loc ~pos =
15
+ match loc |> CursorPosition. classifyLocationLoc ~pos with
16
+ | CursorPosition. EmptyLoc -> emptyLocDenom
17
+ | HasCursor -> hasCursorDenom
18
+ | NoCursor -> noCursorDenom
19
+
20
+ let printLocDenominatorPos pos ~posStart ~posEnd =
21
+ match CursorPosition. classifyPositions pos ~pos Start ~pos End with
22
+ | CursorPosition. EmptyLoc -> emptyLocDenom
23
+ | HasCursor -> hasCursorDenom
24
+ | NoCursor -> noCursorDenom
25
+
26
+ let addIndentation indentation =
27
+ let rec indent str indentation =
28
+ if indentation < 1 then str else indent (str ^ " " ) (indentation - 1 )
29
+ in
30
+ indent " " indentation
31
+
32
+ let printAttributes attributes =
33
+ match List. length attributes with
34
+ | 0 -> " "
35
+ | _ ->
36
+ " ["
37
+ ^ (attributes
38
+ |> List. map (fun ({Location. txt} , _payload ) -> " @" ^ txt)
39
+ |> String. concat " ," )
40
+ ^ " ]"
41
+
42
+ let printConstant const =
43
+ match const with
44
+ | Parsetree. Pconst_integer (s , _ ) -> " Pconst_integer(" ^ s ^ " )"
45
+ | Pconst_char c -> " Pconst_char(" ^ String. make 1 c ^ " )"
46
+ | Pconst_string (s , delim ) ->
47
+ let delim =
48
+ match delim with
49
+ | None -> " "
50
+ | Some delim -> delim ^ " "
51
+ in
52
+ " Pconst_string(" ^ delim ^ s ^ delim ^ " )"
53
+ | Pconst_float (s , _ ) -> " Pconst_float(" ^ s ^ " )"
54
+
55
+ let printCoreType typ ~pos =
56
+ printAttributes typ.Parsetree. ptyp_attributes
57
+ ^ (typ.ptyp_loc |> printLocDenominator ~pos )
58
+ ^
59
+ match typ.ptyp_desc with
60
+ | Ptyp_any -> " Ptyp_any"
61
+ | Ptyp_var name -> " Ptyp_var(" ^ str name ^ " )"
62
+ | Ptyp_constr (loc , _types ) ->
63
+ " Ptyp_constr("
64
+ ^ (loc |> printLocDenominatorLoc ~pos )
65
+ ^ (Utils. flattenLongIdent loc.txt |> ident |> str)
66
+ ^ " )"
67
+ | Ptyp_variant _ -> " Ptyp_variant(<unimplemented>)"
68
+ | _ -> " <unimplemented_ptyp_desc>"
69
+
70
+ let rec printPattern pattern ~pos ~indentation =
71
+ printAttributes pattern.Parsetree. ppat_attributes
72
+ ^ (pattern.ppat_loc |> printLocDenominator ~pos )
73
+ ^
74
+ match pattern.Parsetree. ppat_desc with
75
+ | Ppat_or (pat1 , pat2 ) ->
76
+ " Ppat_or(\n "
77
+ ^ addIndentation (indentation + 1 )
78
+ ^ printPattern pat1 ~pos ~indentation: (indentation + 2 )
79
+ ^ " ,\n "
80
+ ^ addIndentation (indentation + 1 )
81
+ ^ printPattern pat2 ~pos ~indentation: (indentation + 2 )
82
+ ^ " \n " ^ addIndentation indentation ^ " )"
83
+ | Ppat_extension (({txt} as loc ), _ ) ->
84
+ " Ppat_extension(%" ^ (loc |> printLocDenominatorLoc ~pos ) ^ txt ^ " )"
85
+ | Ppat_var ({txt} as loc ) ->
86
+ " Ppat_var(" ^ (loc |> printLocDenominatorLoc ~pos ) ^ txt ^ " )"
87
+ | Ppat_constant const -> " Ppat_constant(" ^ printConstant const ^ " )"
88
+ | Ppat_construct (({txt} as loc ), maybePat ) ->
89
+ " Ppat_construct("
90
+ ^ (loc |> printLocDenominatorLoc ~pos )
91
+ ^ (Utils. flattenLongIdent txt |> ident |> str)
92
+ ^ (match maybePat with
93
+ | None -> " "
94
+ | Some pat -> " ," ^ printPattern pat ~pos ~indentation )
95
+ ^ " )"
96
+ | Ppat_variant (label , maybePat ) ->
97
+ " Ppat_variant(" ^ str label
98
+ ^ (match maybePat with
99
+ | None -> " "
100
+ | Some pat -> " ," ^ printPattern pat ~pos ~indentation )
101
+ ^ " )"
102
+ | Ppat_record (fields , _ ) ->
103
+ " Ppat_record(\n "
104
+ ^ addIndentation (indentation + 1 )
105
+ ^ " fields:\n "
106
+ ^ (fields
107
+ |> List. map (fun ((Location. {txt} as loc ), pat ) ->
108
+ addIndentation (indentation + 2 )
109
+ ^ (loc |> printLocDenominatorLoc ~pos )
110
+ ^ (Utils. flattenLongIdent txt |> ident |> str)
111
+ ^ " : "
112
+ ^ printPattern pat ~pos ~indentation: (indentation + 2 ))
113
+ |> String. concat " \n " )
114
+ ^ " \n " ^ addIndentation indentation ^ " )"
115
+ | Ppat_tuple patterns ->
116
+ " Ppat_tuple(\n "
117
+ ^ (patterns
118
+ |> List. map (fun pattern ->
119
+ addIndentation (indentation + 2 )
120
+ ^ (pattern |> printPattern ~pos ~indentation: (indentation + 2 )))
121
+ |> String. concat " ,\n " )
122
+ ^ " \n " ^ addIndentation indentation ^ " )"
123
+ | Ppat_any -> " Ppat_any"
124
+ | Ppat_constraint (pattern , typ ) ->
125
+ " Ppat_constraint(\n "
126
+ ^ addIndentation (indentation + 1 )
127
+ ^ printCoreType typ ~pos ^ " ,\n "
128
+ ^ addIndentation (indentation + 1 )
129
+ ^ (pattern |> printPattern ~pos ~indentation: (indentation + 1 ))
130
+ ^ " \n " ^ addIndentation indentation ^ " )"
131
+ | v -> Printf. sprintf " <unimplemented_ppat_desc: %s>" (Utils. identifyPpat v)
132
+
133
+ and printCase case ~pos ~indentation ~caseNum =
134
+ addIndentation indentation
135
+ ^ Printf. sprintf " case %i:\n " caseNum
136
+ ^ addIndentation (indentation + 1 )
137
+ ^ " pattern"
138
+ ^ (case.Parsetree. pc_lhs.ppat_loc |> printLocDenominator ~pos )
139
+ ^ " :\n "
140
+ ^ addIndentation (indentation + 2 )
141
+ ^ printPattern case.Parsetree. pc_lhs ~pos ~indentation
142
+ ^ " \n "
143
+ ^ addIndentation (indentation + 1 )
144
+ ^ " expr"
145
+ ^ (case.Parsetree. pc_rhs.pexp_loc |> printLocDenominator ~pos )
146
+ ^ " :\n "
147
+ ^ addIndentation (indentation + 2 )
148
+ ^ printExprItem case.pc_rhs ~pos ~indentation: (indentation + 2 )
149
+
150
+ and printExprItem expr ~pos ~indentation =
151
+ printAttributes expr.Parsetree. pexp_attributes
152
+ ^ (expr.pexp_loc |> printLocDenominator ~pos )
153
+ ^
154
+ match expr.Parsetree. pexp_desc with
155
+ | Pexp_match (matchExpr , cases ) ->
156
+ " Pexp_match("
157
+ ^ printExprItem matchExpr ~pos ~indentation: 0
158
+ ^ " )\n "
159
+ ^ (cases
160
+ |> List. mapi (fun caseNum case ->
161
+ printCase case ~pos ~case Num:(caseNum + 1 )
162
+ ~indentation: (indentation + 1 ))
163
+ |> String. concat " \n " )
164
+ | Pexp_ident {txt} ->
165
+ " Pexp_ident:" ^ (Utils. flattenLongIdent txt |> SharedTypes. ident)
166
+ | Pexp_apply (expr , args ) ->
167
+ let printLabel labelled ~pos =
168
+ match labelled with
169
+ | None -> " <unlabelled>"
170
+ | Some labelled ->
171
+ printLocDenominatorPos pos ~pos Start:labelled.posStart
172
+ ~pos End:labelled.posEnd
173
+ ^ " ~"
174
+ ^ if labelled.opt then " ?" else " " ^ labelled.name
175
+ in
176
+ let args = extractExpApplyArgs ~args in
177
+ " Pexp_apply(\n "
178
+ ^ addIndentation (indentation + 1 )
179
+ ^ " expr:\n "
180
+ ^ addIndentation (indentation + 2 )
181
+ ^ printExprItem expr ~pos ~indentation: (indentation + 2 )
182
+ ^ " \n "
183
+ ^ addIndentation (indentation + 1 )
184
+ ^ " args:\n "
185
+ ^ (args
186
+ |> List. map (fun arg ->
187
+ addIndentation (indentation + 2 )
188
+ ^ printLabel arg.label ~pos ^ " =\n "
189
+ ^ addIndentation (indentation + 3 )
190
+ ^ printExprItem arg.exp ~pos ~indentation: (indentation + 3 ))
191
+ |> String. concat " ,\n " )
192
+ ^ " \n " ^ addIndentation indentation ^ " )"
193
+ | Pexp_constant constant -> " Pexp_constant(" ^ printConstant constant ^ " )"
194
+ | Pexp_construct (({txt} as loc ), maybeExpr ) ->
195
+ " Pexp_construct("
196
+ ^ (loc |> printLocDenominatorLoc ~pos )
197
+ ^ (Utils. flattenLongIdent txt |> ident |> str)
198
+ ^ (match maybeExpr with
199
+ | None -> " "
200
+ | Some expr -> " , " ^ printExprItem expr ~pos ~indentation )
201
+ ^ " )"
202
+ | Pexp_variant (label , maybeExpr ) ->
203
+ " Pexp_variant(" ^ str label
204
+ ^ (match maybeExpr with
205
+ | None -> " "
206
+ | Some expr -> " ," ^ printExprItem expr ~pos ~indentation )
207
+ ^ " )"
208
+ | Pexp_fun (arg , _maybeDefaultArgExpr , pattern , nextExpr ) ->
209
+ " Pexp_fun(\n "
210
+ ^ addIndentation (indentation + 1 )
211
+ ^ " arg: "
212
+ ^ (match arg with
213
+ | Nolabel -> " Nolabel"
214
+ | Labelled name -> " Labelled(" ^ name ^ " )"
215
+ | Optional name -> " Optional(" ^ name ^ " )" )
216
+ ^ " ,\n "
217
+ ^ addIndentation (indentation + 2 )
218
+ ^ " pattern: "
219
+ ^ printPattern pattern ~pos ~indentation: (indentation + 2 )
220
+ ^ " ,\n "
221
+ ^ addIndentation (indentation + 1 )
222
+ ^ " next expr:\n "
223
+ ^ addIndentation (indentation + 2 )
224
+ ^ printExprItem nextExpr ~pos ~indentation: (indentation + 2 )
225
+ ^ " \n " ^ addIndentation indentation ^ " )"
226
+ | Pexp_extension (({txt} as loc ), _ ) ->
227
+ " Pexp_extension(%" ^ (loc |> printLocDenominatorLoc ~pos ) ^ txt ^ " )"
228
+ | Pexp_assert expr ->
229
+ " Pexp_assert(" ^ printExprItem expr ~pos ~indentation ^ " )"
230
+ | Pexp_field (exp , loc ) ->
231
+ " Pexp_field("
232
+ ^ (loc |> printLocDenominatorLoc ~pos )
233
+ ^ printExprItem exp ~pos ~indentation
234
+ ^ " )"
235
+ | Pexp_record (fields , _ ) ->
236
+ " Pexp_record(\n "
237
+ ^ addIndentation (indentation + 1 )
238
+ ^ " fields:\n "
239
+ ^ (fields
240
+ |> List. map (fun ((Location. {txt} as loc ), expr ) ->
241
+ addIndentation (indentation + 2 )
242
+ ^ (loc |> printLocDenominatorLoc ~pos )
243
+ ^ (Utils. flattenLongIdent txt |> ident |> str)
244
+ ^ " : "
245
+ ^ printExprItem expr ~pos ~indentation: (indentation + 2 ))
246
+ |> String. concat " \n " )
247
+ ^ " \n " ^ addIndentation indentation ^ " )"
248
+ | Pexp_tuple exprs ->
249
+ " Pexp_tuple(\n "
250
+ ^ (exprs
251
+ |> List. map (fun expr ->
252
+ addIndentation (indentation + 2 )
253
+ ^ (expr |> printExprItem ~pos ~indentation: (indentation + 2 )))
254
+ |> String. concat " ,\n " )
255
+ ^ " \n " ^ addIndentation indentation ^ " )"
256
+ | v -> Printf. sprintf " <unimplemented_pexp_desc: %s>" (Utils. identifyPexp v)
257
+
258
+ let printValueBinding value ~pos ~indentation =
259
+ printAttributes value.Parsetree. pvb_attributes
260
+ ^ " value" ^ " :\n "
261
+ ^ addIndentation (indentation + 1 )
262
+ ^ (value.pvb_pat |> printPattern ~pos ~indentation: (indentation + 1 ))
263
+ ^ " \n " ^ addIndentation indentation ^ " expr:\n "
264
+ ^ addIndentation (indentation + 1 )
265
+ ^ printExprItem value.pvb_expr ~pos ~indentation: (indentation + 1 )
266
+
267
+ let printStructItem structItem ~pos ~source =
268
+ match structItem.Parsetree. pstr_loc |> CursorPosition. classifyLoc ~pos with
269
+ | HasCursor -> (
270
+ let startOffset =
271
+ match Pos. positionToOffset source (structItem.pstr_loc |> Loc. start) with
272
+ | None -> 0
273
+ | Some offset -> offset
274
+ in
275
+ let endOffset =
276
+ (* Include the next line of the source since that will hold the ast comment pointing to the position.
277
+ Caveat: this only works for single line sources with a comment on the next line. Will need to be
278
+ adapted if that's not the only use case.*)
279
+ let line, _col = structItem.pstr_loc |> Loc. end_ in
280
+ match Pos. positionToOffset source (line + 2 , 0 ) with
281
+ | None -> 0
282
+ | Some offset -> offset
283
+ in
284
+
285
+ (" \n Source:\n // "
286
+ ^ String. sub source startOffset (endOffset - startOffset)
287
+ ^ " \n " )
288
+ ^ printLocDenominator structItem.pstr_loc ~pos
289
+ ^
290
+ match structItem.pstr_desc with
291
+ | Pstr_eval (expr , _attributes ) ->
292
+ " Pstr_eval(\n " ^ printExprItem expr ~pos ~indentation: 1 ^ " \n )"
293
+ | Pstr_value (recFlag , values ) ->
294
+ " Pstr_value(\n "
295
+ ^ (match recFlag with
296
+ | Recursive -> " rec,\n "
297
+ | Nonrecursive -> " " )
298
+ ^ (values
299
+ |> List. map (fun value ->
300
+ addIndentation 1 ^ printValueBinding value ~pos ~indentation: 1 )
301
+ |> String. concat " ,\n " )
302
+ ^ " \n )"
303
+ | _ -> " <structure_item_not_implemented>" )
304
+ | _ -> " "
305
+
306
+ let dump ~currentFile ~pos =
307
+ let {Res_driver. parsetree = structure; source} =
308
+ Res_driver. parsingEngine.parseImplementation ~for Printer:true
309
+ ~filename: currentFile
310
+ in
311
+
312
+ print_endline
313
+ (structure
314
+ |> List. map (fun structItem -> printStructItem structItem ~pos ~source )
315
+ |> String. concat " " )
0 commit comments