1
1
module Tt = Ppx_types_migrate
2
2
3
+ type error = {loc : Location .t ; error : string }
4
+
5
+ exception Error of error
6
+
7
+ let raise_error ~loc error = raise (Error {loc; error})
8
+
3
9
let lazy_env =
4
10
lazy
5
11
( (* It is important that the typing environment is not evaluated
@@ -66,9 +72,12 @@ let try_find_module_type ~loc env lid =
66
72
Some
67
73
( match modtype_decl.mtd_type with
68
74
| None ->
69
- Location. raise_errorf ~loc
70
- " [%%import]: cannot access the signature of the abstract module %s"
71
- (string_of_lid lid)
75
+ let error =
76
+ Printf. sprintf
77
+ " [%%import]: cannot access the signature of the abstract module %s"
78
+ (string_of_lid lid)
79
+ in
80
+ raise_error ~loc error
72
81
| Some module_type -> module_type )
73
82
with Not_found -> None
74
83
@@ -87,14 +96,24 @@ let open_module_type ~loc env lid module_type =
87
96
match try_open_module_type env module_type with
88
97
| Some sig_items -> sig_items
89
98
| None ->
90
- Location. raise_errorf ~loc " [%%import]: cannot find the components of %s"
91
- (string_of_lid lid)
99
+ let error =
100
+ Printf. sprintf " [%%import]: cannot find the components of %s"
101
+ (string_of_lid lid)
102
+ in
103
+ raise_error ~loc error
92
104
93
105
let locate_sig ~loc env lid =
94
106
let head, path =
95
- match Ppxlib.Longident. flatten_exn lid with
96
- | head :: path -> (Longident. Lident head, path)
97
- | _ -> assert false
107
+ try
108
+ match Ppxlib.Longident. flatten_exn lid with
109
+ | head :: path -> (Longident. Lident head, path)
110
+ | _ -> assert false
111
+ with Invalid_argument _ ->
112
+ let error =
113
+ Printf. sprintf " [%%import] cannot import a functor application %s"
114
+ (string_of_lid lid)
115
+ in
116
+ raise_error ~loc error
98
117
in
99
118
let head_module_type =
100
119
match
@@ -103,8 +122,10 @@ let locate_sig ~loc env lid =
103
122
| Some mty , _ -> mty
104
123
| None , (lazy (Some mty )) -> mty
105
124
| None , (lazy None) ->
106
- Location. raise_errorf ~loc " [%%import]: cannot locate module %s"
107
- (string_of_lid lid)
125
+ let error =
126
+ Printf. sprintf " [%%import]: cannot locate module %s" (string_of_lid lid)
127
+ in
128
+ raise_error ~loc error
108
129
in
109
130
let get_sub_module_type (lid , module_type ) path_item =
110
131
let sig_items = open_module_type ~loc env lid module_type in
@@ -117,9 +138,11 @@ let locate_sig ~loc env lid =
117
138
md_type
118
139
| _ :: sig_items -> loop sig_items
119
140
| [] ->
120
- Location. raise_errorf ~loc
121
- " [%%import]: cannot find the signature of %s in %s" path_item
122
- (string_of_lid lid)
141
+ let error =
142
+ Printf. sprintf " [%%import]: cannot find the signature of %s in %s"
143
+ path_item (string_of_lid lid)
144
+ in
145
+ raise_error ~loc error
123
146
in
124
147
let sub_module_type =
125
148
loop (List. map Compat. migrate_signature_item sig_items)
@@ -148,8 +171,11 @@ let get_type_decl ~loc sig_items parent_lid elem =
148
171
in
149
172
match try_get_tsig_item select_type ~loc sig_items elem with
150
173
| None ->
151
- Location. raise_errorf " [%%import]: cannot find the type %s in %s" elem
152
- (string_of_lid parent_lid)
174
+ let error =
175
+ Printf. sprintf " [%%import]: cannot find the type %s in %s" elem
176
+ (string_of_lid parent_lid)
177
+ in
178
+ raise_error ~loc error
153
179
| Some decl -> decl
154
180
155
181
let get_modtype_decl ~loc sig_items parent_lid elem =
@@ -160,8 +186,11 @@ let get_modtype_decl ~loc sig_items parent_lid elem =
160
186
in
161
187
match try_get_tsig_item select_modtype ~loc sig_items elem with
162
188
| None ->
163
- Location. raise_errorf " [%%import]: cannot find the module type %s in %s"
164
- elem (string_of_lid parent_lid)
189
+ let error =
190
+ Printf. sprintf " [%%import]: cannot find the module type %s in %s" elem
191
+ (string_of_lid parent_lid)
192
+ in
193
+ raise_error ~loc error
165
194
| Some decl -> decl
166
195
167
196
let longident_of_path = Untypeast. lident_of_path
@@ -239,10 +268,12 @@ let ptype_decl_of_ttype_decl ~manifest ~subst ptype_name
239
268
ttype_decl.type_params ptype_args
240
269
|> List. concat
241
270
with Invalid_argument _ ->
242
- Location. raise_errorf ~loc: ptyp_loc
243
- " Imported type has %d parameter(s), but %d are passed"
244
- (List. length ttype_decl.type_params)
245
- (List. length ptype_args) )
271
+ let error =
272
+ Printf. sprintf " Imported type has %d parameter(s), but %d are passed"
273
+ (List. length ttype_decl.type_params)
274
+ (List. length ptype_args)
275
+ in
276
+ raise_error ~loc: ptyp_loc error )
246
277
| None -> []
247
278
| _ -> assert false
248
279
in
@@ -337,8 +368,7 @@ let subst_of_manifest ({ptyp_attributes; ptyp_loc; _} : Ppxlib.core_type) =
337
368
; ptyp_attributes = pexp_attributes
338
369
; ptyp_desc = Ptyp_constr (dst, [] ) } )
339
370
:: subst_of_expr rest
340
- | {pexp_loc; _} ->
341
- Location. raise_errorf ~loc: pexp_loc " Invalid [@with] syntax"
371
+ | {pexp_loc; _} -> raise_error ~loc: pexp_loc " Invalid [@with] syntax"
342
372
in
343
373
let find_attr s attrs =
344
374
try
@@ -348,18 +378,25 @@ let subst_of_manifest ({ptyp_attributes; ptyp_loc; _} : Ppxlib.core_type) =
348
378
match find_attr " with" ptyp_attributes with
349
379
| None -> []
350
380
| Some (PStr [{pstr_desc = Pstr_eval (expr , [] ); _} ]) -> subst_of_expr expr
351
- | Some _ -> Location. raise_errorf ~loc: ptyp_loc " Invalid [@with] syntax"
381
+ | Some _ -> raise_error ~loc: ptyp_loc " Invalid [@with] syntax"
352
382
353
383
let uncapitalize = String. uncapitalize_ascii
354
384
355
- let is_self_reference ~input_name lid =
385
+ let is_self_reference ~input_name ~ loc lid =
356
386
let fn =
357
387
input_name |> Filename. basename |> Filename. chop_extension |> uncapitalize
358
388
in
359
389
match lid with
360
- | Ppxlib. Ldot _ ->
361
- let mn = Ppxlib.Longident. flatten_exn lid |> List. hd |> uncapitalize in
362
- fn = mn
390
+ | Ppxlib. Ldot _ -> (
391
+ try
392
+ let mn = Ppxlib.Longident. flatten_exn lid |> List. hd |> uncapitalize in
393
+ fn = mn
394
+ with Invalid_argument _ ->
395
+ let error =
396
+ Printf. sprintf " [%%import] cannot import a functor application %s"
397
+ (string_of_lid lid)
398
+ in
399
+ raise_error ~loc error )
363
400
| _ -> false
364
401
365
402
let type_declaration ~tool_name ~input_name (type_decl : Ppxlib.type_declaration )
@@ -370,47 +407,56 @@ let type_declaration ~tool_name ~input_name (type_decl : Ppxlib.type_declaration
370
407
; ptype_name
371
408
; ptype_manifest =
372
409
Some ({ptyp_desc = Ptyp_constr ({txt = lid; loc}, _); _} as manifest)
373
- ; _ } ->
374
- if tool_name = " ocamldep" then
375
- (* Just put it as manifest *)
376
- if is_self_reference ~input_name lid then
377
- {type_decl with ptype_manifest = None }
378
- else {type_decl with ptype_manifest = Some manifest}
379
- else
380
- Ast_helper. with_default_loc loc (fun () ->
381
- let ttype_decl =
382
- let env = Lazy. force lazy_env in
383
- match lid with
384
- | Lapply _ ->
385
- Location. raise_errorf ~loc
386
- " [%%import] cannot import a functor application %s"
387
- (string_of_lid lid)
388
- | Lident _ as head_id ->
389
- (* In this case, we know for sure that the user intends this lident
390
- as a type name, so we use Typetexp.find_type and let the failure
391
- cases propagate to the user. *)
392
- Compat. find_type env ~loc head_id |> snd
393
- | Ldot (parent_id , elem ) ->
394
- let sig_items = locate_sig ~loc env parent_id in
395
- get_type_decl ~loc sig_items parent_id elem
396
- in
397
- let m, s =
398
- if is_self_reference ~input_name lid then (None , [] )
399
- else
400
- let subst = subst_of_manifest manifest in
401
- let subst =
402
- subst
403
- @ [ ( `Lid (Lident (Longident. last_exn lid))
404
- , Ast_helper.Typ. constr
405
- {txt = Lident ptype_name.txt; loc = ptype_name.loc}
406
- [] ) ]
407
- in
408
- (Some manifest, subst)
409
- in
410
- let ptype_decl =
411
- ptype_decl_of_ttype_decl ~manifest: m ~subst: s ptype_name ttype_decl
412
- in
413
- {ptype_decl with ptype_attributes} )
410
+ ; _ } -> (
411
+ try
412
+ if tool_name = " ocamldep" then
413
+ (* Just put it as manifest *)
414
+ if is_self_reference ~input_name ~loc lid then
415
+ {type_decl with ptype_manifest = None }
416
+ else {type_decl with ptype_manifest = Some manifest}
417
+ else
418
+ Ast_helper. with_default_loc loc (fun () ->
419
+ let ttype_decl =
420
+ let env = Lazy. force lazy_env in
421
+ match lid with
422
+ | Lapply _ ->
423
+ let error =
424
+ Printf. sprintf
425
+ " [%%import] cannot import a functor application %s"
426
+ (string_of_lid lid)
427
+ in
428
+ raise_error ~loc error
429
+ | Lident _ as head_id ->
430
+ (* In this case, we know for sure that the user intends this lident
431
+ as a type name, so we use Typetexp.find_type and let the failure
432
+ cases propagate to the user. *)
433
+ Compat. find_type env ~loc head_id |> snd
434
+ | Ldot (parent_id , elem ) ->
435
+ let sig_items = locate_sig ~loc env parent_id in
436
+ get_type_decl ~loc sig_items parent_id elem
437
+ in
438
+ let m, s =
439
+ if is_self_reference ~input_name ~loc lid then (None , [] )
440
+ else
441
+ let subst = subst_of_manifest manifest in
442
+ let subst =
443
+ subst
444
+ @ [ ( `Lid (Lident (Longident. last_exn lid))
445
+ , Ast_helper.Typ. constr
446
+ {txt = Lident ptype_name.txt; loc = ptype_name.loc}
447
+ [] ) ]
448
+ in
449
+ (Some manifest, subst)
450
+ in
451
+ let ptype_decl =
452
+ ptype_decl_of_ttype_decl ~manifest: m ~subst: s ptype_name
453
+ ttype_decl
454
+ in
455
+ {ptype_decl with ptype_attributes} )
456
+ with Error {loc; error} ->
457
+ let ext = Ppxlib.Location. error_extensionf ~loc " %s" error in
458
+ let core_type = Ast_builder.Default. ptyp_extension ~loc ext in
459
+ {type_decl with ptype_manifest = Some core_type} )
414
460
| _ -> type_decl
415
461
416
462
let rec cut_tsig_block_of_rec_types accu (tsig : Compat.signature_item_407 list )
@@ -464,42 +510,60 @@ let rec psig_of_tsig ~subst (tsig : Compat.signature_item_407 list) :
464
510
465
511
let module_type ~tool_name ~input_name (package_type : Ppxlib.package_type ) =
466
512
let open Ppxlib in
467
- let ({txt = lid; loc} as alias), subst = package_type in
468
- if tool_name = " ocamldep" then
469
- if is_self_reference ~input_name lid then
470
- (* Create a dummy module type to break the circular dependency *)
471
- Ast_helper.Mty. mk ~attrs: [] (Pmty_signature [] )
472
- else (* Just put it as alias *)
473
- Ast_helper.Mty. mk ~attrs: [] (Pmty_alias alias)
474
- else
475
- Ppxlib.Ast_helper. with_default_loc loc (fun () ->
476
- let env = Lazy. force lazy_env in
477
- let tmodtype_decl =
478
- match lid with
479
- | Longident. Lapply _ ->
480
- Location. raise_errorf ~loc
481
- " [%%import] cannot import a functor application %s"
482
- (string_of_lid lid)
483
- | Longident. Lident _ as head_id ->
484
- (* In this case, we know for sure that the user intends this lident
485
- as a module type name, so we use Typetexp.find_type and
486
- let the failure cases propagate to the user. *)
487
- Compat. find_modtype env ~loc head_id |> snd
488
- | Longident. Ldot (parent_id , elem ) ->
489
- let sig_items = locate_sig ~loc env parent_id in
490
- get_modtype_decl ~loc sig_items parent_id elem
491
- in
492
- match tmodtype_decl with
493
- | {mtd_type = Some (Mty_signature tsig ); _} ->
494
- let subst = List. map (fun ({txt; _} , typ ) -> (`Lid txt, typ)) subst in
495
- let psig =
496
- psig_of_tsig ~subst (List. map Compat. migrate_signature_item tsig)
513
+ try
514
+ let ({txt = lid; loc} as alias), subst = package_type in
515
+ if tool_name = " ocamldep" then
516
+ if is_self_reference ~input_name ~loc lid then
517
+ (* Create a dummy module type to break the circular dependency *)
518
+ Ast_helper.Mty. mk ~attrs: [] (Pmty_signature [] )
519
+ else
520
+ (* Just put it as alias *)
521
+ Ast_helper.Mty. mk ~attrs: [] (Pmty_alias alias)
522
+ else
523
+ Ppxlib.Ast_helper. with_default_loc loc (fun () ->
524
+ let env = Lazy. force lazy_env in
525
+ let tmodtype_decl =
526
+ match lid with
527
+ | Longident. Lapply _ ->
528
+ let error =
529
+ Printf. sprintf
530
+ " [%%import] cannot import a functor application %s"
531
+ (string_of_lid lid)
532
+ in
533
+ raise_error ~loc error
534
+ | Longident. Lident _ as head_id ->
535
+ (* In this case, we know for sure that the user intends this lident
536
+ as a module type name, so we use Typetexp.find_type and
537
+ let the failure cases propagate to the user. *)
538
+ Compat. find_modtype env ~loc head_id |> snd
539
+ | Longident. Ldot (parent_id , elem ) ->
540
+ let sig_items = locate_sig ~loc env parent_id in
541
+ get_modtype_decl ~loc sig_items parent_id elem
497
542
in
498
- Ast_helper.Mty. mk ~attrs: [] (Pmty_signature psig)
499
- | {mtd_type = None ; _} ->
500
- Location. raise_errorf ~loc " Imported module is abstract"
501
- | _ ->
502
- Location. raise_errorf ~loc " Imported module is indirectly defined" )
543
+ match tmodtype_decl with
544
+ | {mtd_type = Some (Mty_signature tsig ); _} ->
545
+ let subst =
546
+ List. map (fun ({txt; _} , typ ) -> (`Lid txt, typ)) subst
547
+ in
548
+ let psig =
549
+ psig_of_tsig ~subst (List. map Compat. migrate_signature_item tsig)
550
+ in
551
+ Ast_helper.Mty. mk ~attrs: [] (Pmty_signature psig)
552
+ | {mtd_type = None ; _} ->
553
+ let ext =
554
+ Ppxlib.Location. error_extensionf ~loc
555
+ " Imported module is abstract"
556
+ in
557
+ Ast_builder.Default. pmty_extension ~loc ext
558
+ | _ ->
559
+ let ext =
560
+ Ppxlib.Location. error_extensionf ~loc
561
+ " Imported module is indirectly defined"
562
+ in
563
+ Ast_builder.Default. pmty_extension ~loc ext )
564
+ with Error {loc; error} ->
565
+ let ext = Ppxlib.Location. error_extensionf ~loc " %s" error in
566
+ Ast_builder.Default. pmty_extension ~loc ext
503
567
504
568
let type_declaration_expand ~ctxt rec_flag type_decls =
505
569
let loc = Ppxlib.Expansion_context.Extension. extension_point_loc ctxt in
0 commit comments