11module Tt = Ppx_types_migrate
22
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+
39let lazy_env =
410 lazy
511 ( (* It is important that the typing environment is not evaluated
@@ -66,9 +72,12 @@ let try_find_module_type ~loc env lid =
6672 Some
6773 ( match modtype_decl.mtd_type with
6874 | 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
7281 | Some module_type -> module_type )
7382 with Not_found -> None
7483
@@ -87,14 +96,24 @@ let open_module_type ~loc env lid module_type =
8796 match try_open_module_type env module_type with
8897 | Some sig_items -> sig_items
8998 | 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
92104
93105let locate_sig ~loc env lid =
94106 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
98117 in
99118 let head_module_type =
100119 match
@@ -103,8 +122,10 @@ let locate_sig ~loc env lid =
103122 | Some mty , _ -> mty
104123 | None , (lazy (Some mty )) -> mty
105124 | 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
108129 in
109130 let get_sub_module_type (lid , module_type ) path_item =
110131 let sig_items = open_module_type ~loc env lid module_type in
@@ -117,9 +138,11 @@ let locate_sig ~loc env lid =
117138 md_type
118139 | _ :: sig_items -> loop sig_items
119140 | [] ->
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
123146 in
124147 let sub_module_type =
125148 loop (List. map Compat. migrate_signature_item sig_items)
@@ -148,8 +171,11 @@ let get_type_decl ~loc sig_items parent_lid elem =
148171 in
149172 match try_get_tsig_item select_type ~loc sig_items elem with
150173 | 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
153179 | Some decl -> decl
154180
155181let get_modtype_decl ~loc sig_items parent_lid elem =
@@ -160,8 +186,11 @@ let get_modtype_decl ~loc sig_items parent_lid elem =
160186 in
161187 match try_get_tsig_item select_modtype ~loc sig_items elem with
162188 | 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
165194 | Some decl -> decl
166195
167196let longident_of_path = Untypeast. lident_of_path
@@ -239,10 +268,12 @@ let ptype_decl_of_ttype_decl ~manifest ~subst ptype_name
239268 ttype_decl.type_params ptype_args
240269 |> List. concat
241270 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 )
246277 | None -> []
247278 | _ -> assert false
248279 in
@@ -337,8 +368,7 @@ let subst_of_manifest ({ptyp_attributes; ptyp_loc; _} : Ppxlib.core_type) =
337368 ; ptyp_attributes = pexp_attributes
338369 ; ptyp_desc = Ptyp_constr (dst, [] ) } )
339370 :: 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"
342372 in
343373 let find_attr s attrs =
344374 try
@@ -348,18 +378,25 @@ let subst_of_manifest ({ptyp_attributes; ptyp_loc; _} : Ppxlib.core_type) =
348378 match find_attr " with" ptyp_attributes with
349379 | None -> []
350380 | 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"
352382
353383let uncapitalize = String. uncapitalize_ascii
354384
355- let is_self_reference ~input_name lid =
385+ let is_self_reference ~input_name ~ loc lid =
356386 let fn =
357387 input_name |> Filename. basename |> Filename. chop_extension |> uncapitalize
358388 in
359389 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 )
363400 | _ -> false
364401
365402let 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
370407 ; ptype_name
371408 ; ptype_manifest =
372409 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} )
414460 | _ -> type_decl
415461
416462let 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) :
464510
465511let module_type ~tool_name ~input_name (package_type : Ppxlib.package_type ) =
466512 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
497542 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
503567
504568let type_declaration_expand ~ctxt rec_flag type_decls =
505569 let loc = Ppxlib.Expansion_context.Extension. extension_point_loc ctxt in
0 commit comments