3 (* Copyright Jeremy Yallop 2007.
4 This file is free software, distributed under the MIT license.
5 See the file COPYING for details.
8 (* Extend the OCaml grammar to include the `deriving' clause after
9 type declarations in structure and signatures. *)
13 module Deriving
(Syntax
: Camlp4.Sig.Camlp4Syntax
) =
19 let fatal_error loc msg
=
20 Syntax.print_warning loc msg
;
23 let display_errors loc f p
=
27 Base.Underivable msg
| Failure msg
->
30 let derive proj
(loc
: Loc.t
) tdecls classname
=
31 let context = display_errors loc
(Base.setup_context loc
) tdecls
in
33 (proj
(Base.find classname
)) (loc
, context, tdecls
)
35 let derive_str loc
(tdecls
: Type.decl list
) classname
: Ast.str_item
=
36 derive fst loc tdecls classname
38 let derive_sig loc tdecls classname
: Ast.sig_item
=
39 derive snd loc tdecls classname
42 DELETE_RULE Gram str_item
: "type"; type_declaration END
43 DELETE_RULE Gram sig_item
: "type"; type_declaration END
49 [[ "type"; types
= type_declaration
-> <:str_item
< type $types$
>>
50 | "type"; types
= type_declaration
; "deriving"; "("; cl
= LIST0
[x
= UIDENT
-> x
] SEP
","; ")" ->
51 let decls = display_errors loc
Type.Translate.decls types
in
52 let module U
= Type.Untranslate
(struct let loc = loc end) in
53 let tdecls = List.map
U.decl
decls in
54 <:str_item
< type $list
:tdecls$ $list
:List.map
(derive_str loc decls) cl$
>>
58 [[ "type"; types
= type_declaration
-> <:sig_item
< type $types$
>>
59 | "type"; types
= type_declaration
; "deriving"; "("; cl
= LIST0
[x
= UIDENT
-> x
] SEP
"," ; ")" ->
60 let decls = display_errors loc Type.Translate.decls types
in
61 let module U
= Type.Untranslate
(struct let loc = loc end) in
62 let tdecls = List.concat_map
U.sigdecl
decls in
63 let ms = List.map
(derive_sig loc decls) cl
in
64 <:sig_item
< type $list
:tdecls$ $list
:ms$
>> ]]
71 [e1
= val_longident
; "<" ; t
= ctyp
; ">" ->
73 | <:ident
< $uid
:classname$
. $lid
:methodname$
>> ->
74 if not
(Base.is_registered classname
) then
75 fatal_error loc ("deriving: "^ classname ^
" is not a known `class'")
77 let module U
= Type.Untranslate
(struct let loc = loc end) in
78 let binding = Ast.TyDcl
(loc, "inline", [], t
, []) in
79 let decls = display_errors loc Type.Translate.decls binding in
80 if List.exists
Base.contains_tvars_decl
decls then
81 fatal_error loc ("deriving: type variables cannot be used in `method' instantiations")
83 let tdecls = List.map
U.decl
decls in
84 let m = derive_str loc decls classname
in
85 <:expr
< let module $uid
:classname$
=
89 include $uid
:classname ^
"_inline"$
91 in $uid
:classname$
.$lid
:methodname$
>>
93 fatal_error loc ("deriving: this looks a bit like a method application, but "
94 ^
"the syntax is not valid");
100 module M
= Camlp4.Register.OCamlSyntaxExtension
(Id
)(Deriving
)