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