@@ -45,29 +45,19 @@ type options = {
4545 service : expression option ;
4646}
4747
48- let empty ~loc = pexp_construct ~loc (llid ~loc " EzAPI.Empty" ) None
4948let raw e =
5049 let loc = e.pexp_loc in
51- let e =
52- eapply ~loc (evar ~loc " List.filter_map" ) [ evar ~loc " EzAPI.Mime.parse" ; e ] in
53- pexp_construct ~loc (llid ~loc " EzAPI.Raw" ) @@ Some e
54- let json e =
55- let loc = e.pexp_loc in
56- pexp_construct ~loc (llid ~loc " EzAPI.Json" ) @@ Some e
57-
58- let options ?register ?name loc =
59- let register = match register with
60- | None -> pexp_construct ~loc (llid ~loc " true" ) None
61- | Some register -> register in
62- let name = match name with
63- | None -> [% expr None ]
64- | Some name -> esome (estring ~loc name) in {
65- path = pexp_ident ~loc (llid ~loc " EzAPI.Path.root" );
66- input = empty ~loc ; output = empty ~loc ; errors = [% expr None ]; params = [% expr None ];
67- section = [% expr None ]; name; descr = [% expr None ];
68- security = [% expr None ]; register; input_example = [% expr None ]; hide = [% expr None ];
69- output_example = [% expr None ]; error_type = ptyp_constr ~loc (llid ~loc " exn" ) [] ;
70- security_type = ptyp_constr ~loc (llid ~loc " EzAPI.no_security" ) [] ;
50+ [% expr EzAPI. Raw (List. filter_map EzAPI.Mime. parse [% e e])]
51+
52+ let options loc = {
53+ path = [% expr EzAPI.Path. root];
54+ input = [% expr EzAPI. Empty ];
55+ output = [% expr EzAPI. Empty ];
56+ errors = [% expr None ]; params = [% expr None ];
57+ section = [% expr None ]; name= [% expr None ]; descr = [% expr None ];
58+ security = [% expr None ]; register= [% expr true ]; input_example = [% expr None ];
59+ hide = [% expr None ]; output_example = [% expr None ]; error_type = [% type : exn ];
60+ security_type = [% type : EzAPI. no_security];
7161 debug = false ; directory = None ; service = None
7262}
7363
@@ -100,23 +90,22 @@ let string_literal = function
10090 | Ppxlib. Pconst_string (s , _ , _ ) -> Some s
10191 | _ -> None
10292
103- let get_options ~loc ?name ?(client =false ) p =
104- let register = if not client then None else Some (pexp_construct ~loc (llid ~loc " false" ) None ) in
93+ let get_options ~loc ?(options =options loc) ?name p =
10594 match p with
10695 | PStr [ {pstr_desc= Pstr_eval ({pexp_desc= Pexp_record (l, _); _}, _); _} ] ->
10796 let l = List. filter_map (function ({txt =Lident s ; loc} , e ) -> Some (s, loc, e) | _ -> None ) l in
10897 List. fold_left (fun (name , acc ) (s , loc , e ) -> match s with
109- | "path" -> begin match e.pexp_desc with
98+ | "path" | "p" -> begin match e.pexp_desc with
11099 | Pexp_constant cst ->
111100 begin match string_literal cst with
112101 | Some s -> name, { acc with path = parse_path ~loc: e.pexp_loc s }
113102 | _ -> Format. eprintf " path should be a string literal" ; name, acc
114103 end
115104 | _ -> Format. eprintf " path should be a literal" ; name, acc
116105 end
117- | "input" -> name, { acc with input = json e }
106+ | "input" -> name, { acc with input = [ % expr EzAPI. Json [ % e e]] }
118107 | "raw_input" -> name, { acc with input = raw e }
119- | "output" -> name, { acc with output = json e }
108+ | "output" -> name, { acc with output = [ % expr EzAPI. Json [ % e e]] }
120109 | "raw_output" -> name, { acc with output = raw e }
121110 | "params" -> name, { acc with params = esome e }
122111 | "errors" -> name, { acc with errors = esome e; error_type = ptyp_any ~loc }
@@ -130,8 +119,9 @@ let get_options ~loc ?name ?(client=false) p =
130119 | _ -> Format. eprintf " name should be a string literal" ; name, acc
131120 end
132121 | _ ->
133- Format. eprintf " name should be a literal" ;
134- name, acc
122+ match name with
123+ | Some n -> Some n, { acc with name = [% expr Some [% e estring ~loc n]] }
124+ | _ -> name, acc
135125 end
136126 | "descr" -> name, { acc with descr = esome e }
137127 | "security" -> name, { acc with security = esome e; security_type = ptyp_any ~loc }
@@ -150,20 +140,21 @@ let get_options ~loc ?name ?(client=false) p =
150140 end
151141 | "service" ->
152142 name, { acc with service = Some e; error_type = ptyp_any ~loc ; security_type = ptyp_any ~loc }
153- | _ -> name, acc) (name, options ?register ?name loc ) l
143+ | _ -> name, acc) (name, options) l
154144 | PStr [ {pstr_desc= Pstr_eval ({pexp_desc= Pexp_ident _; _} as e, _); _} ] ->
155- let o = options ?register ?name loc in
156- name, { o with service = Some e; error_type = ptyp_any ~loc ; security_type = ptyp_any ~loc }
145+ name, { options with service = Some e; error_type = ptyp_any ~loc ; security_type = ptyp_any ~loc }
146+ | PStr [ {pstr_desc= Pstr_eval ({pexp_desc= Pexp_constant Pconst_string (s, loc, _); _}, _); _} ] ->
147+ name, { options with path = parse_path ~loc s }
157148 | PStr s ->
158149 Format. eprintf " attribute not understood %a@." Pprintast. structure s;
159- name, options ?register ?name loc
150+ name, options
160151 | _ ->
161152 Format. eprintf " attribute not understood@." ;
162- name, options ?register ?name loc
153+ name, options
163154
164- let service_value ?name ?client ~meth ~loc p =
155+ let service_value ?name ?options ~meth ~loc p =
165156 let meth = pexp_variant ~loc (String. uppercase_ascii meth) None in
166- let name, options = get_options ~loc ?name ?client p in
157+ let name, options = get_options ?name ?options ~loc p in
167158 match name with
168159 | None -> Location. raise_errorf ~loc " service doesn't have a name"
169160 | Some name ->
@@ -344,6 +335,8 @@ let server ~loc p =
344335 [% expr EzLwtSys. run (fun () -> [% e server_aux e])]
345336 | _ -> Location. raise_errorf ~loc " server options not understood"
346337
338+ (* * main mapper *)
339+
347340let deprecate =
348341 let t : (string, unit) Hashtbl.t = Hashtbl. create 10 in
349342 fun s ->
@@ -442,14 +435,52 @@ let transform ?kind () =
442435 (* client service *)
443436 | Pstr_attribute a when List. mem a.attr_name.txt methods ->
444437 deprecate a.attr_name.txt;
445- let service, _, _ = service_value ~client: true ~meth: a.attr_name.txt ~loc: a.attr_loc a.attr_payload in
438+ let loc = a.attr_loc in
439+ let options = { (options loc) with register = [% expr false ] } in
440+ let service, _, _ = service_value ~options ~meth: a.attr_name.txt ~loc: a.attr_loc a.attr_payload in
446441 service :: acc
447442 | Pstr_extension (({txt; loc} , PStr [ { pstr_desc = Pstr_value (_ , [ { pvb_expr; pvb_pat = {ppat_desc =Ppat_var {txt =name ; _} ; _} ; _} ]); _} ]), _ ) when List. mem txt methods ->
448- let service, _, _ = service_value ~name ~client: true ~meth: txt ~loc @@ PStr [ pstr_eval ~loc pvb_expr [] ] in
443+ let options = { (options loc) with register = [% expr false ] } in
444+ let service, _, _ = service_value ~name ~options ~meth: txt ~loc @@ PStr [ pstr_eval ~loc pvb_expr [] ] in
449445 service :: acc
450446 | Pstr_extension (({txt; loc} , p ), _ ) when List. mem txt methods ->
451- let service, _, _ = service_value ~client: true ~meth: txt ~loc p in
447+ let options = { (options loc) with register = [% expr false ] } in
448+ let service, _, _ = service_value ~options ~meth: txt ~loc p in
452449 service :: acc
450+ | Pstr_type (_rec_flag , [ t ]) ->
451+ let loc = t.ptype_loc in
452+ begin match List. find_opt (fun a -> List. mem a.attr_name.txt methods) t.ptype_attributes with
453+ | None -> (super#structure_item it) :: acc
454+ | Some a ->
455+ let meth = a.attr_name.txt in
456+ let enc =
457+ let open Ppx_deriving_encoding_lib.Encoding in
458+ let {enc; _} = expressions t in
459+ enc in
460+ let input, output = match meth with
461+ | "get" | "put" -> [% expr Some EzAPI. Empty ], [% expr EzAPI. Json [% e enc]]
462+ | _ -> [% expr EzAPI. Json [% e enc]], [% expr Some EzAPI. Empty ] in
463+ let options = { (options loc) with register = [% expr false ]; input; output } in
464+ let name = t.ptype_name.txt ^ " _s" in
465+ let service, _, _ = service_value ~name ~options ~meth ~loc a.attr_payload in
466+ service :: it :: acc
467+ end
468+ | Pstr_type (_rec_flag , [ t_input ; t_output ]) ->
469+ let loc = t_input.ptype_loc in
470+ begin match List. find_opt (fun a -> List. mem a.attr_name.txt methods) t_output.ptype_attributes with
471+ | None -> (super#structure_item it) :: acc
472+ | Some a ->
473+ let meth = a.attr_name.txt in
474+ let input, output =
475+ let open Ppx_deriving_encoding_lib.Encoding in
476+ let {enc= enc_input; _} = expressions t_input in
477+ let {enc= enc_output; _} = expressions t_output in
478+ [% expr EzAPI. Json [% e enc_input]], [% expr EzAPI. Json [% e enc_output]] in
479+ let options = { (options loc) with register = [% expr false ]; input; output } in
480+ let name = t_input.ptype_name.txt ^ " _s" in
481+ let service, _, _ = service_value ~name ~options ~meth ~loc a.attr_payload in
482+ service :: it :: acc
483+ end
453484 | _ -> (self#structure_item it) :: acc
454485 ) [] str
455486
@@ -460,3 +491,69 @@ let transform ?kind () =
460491 end
461492
462493let impl ?kind str = (transform ?kind () )#structure str
494+
495+ let deriver_str_gen meth ~loc ~path :_ (_rec_flag , l ) path input output errors params section name
496+ descr security register hide input_example output_example debug =
497+ let options = options loc in
498+ let sname = match l with t :: _ -> Some (t.ptype_name.txt ^ " _s" ) | [] -> None in
499+ let input, output = match meth, l with
500+ | _ , [ t_input; t_output ] ->
501+ [% expr EzAPI. Json ([% e evar ~loc (t_input.ptype_name.txt ^ " _enc" )] () )],
502+ [% expr EzAPI. Json ([% e evar ~loc (t_output.ptype_name.txt ^ " _enc" )] () )]
503+ | ("get" | "put" ), t :: _ ->
504+ Option. value ~default: options.input input,
505+ [% expr EzAPI. Json [% e evar ~loc (t.ptype_name.txt ^ " _enc" )]]
506+ | _ , t :: _ ->
507+ [% expr EzAPI. Json [% e evar ~loc (t.ptype_name.txt ^ " _enc" )]],
508+ Option. value ~default: options.output output
509+ | _ -> Option. value ~default: options.input input, Option. value ~default: options.output output in
510+ let path = match path with
511+ | Some { pexp_desc = Pexp_constant cst ; pexp_loc =loc ; _ } ->
512+ begin match string_literal cst with
513+ | Some s -> parse_path ~loc s
514+ | _ -> Format. eprintf " path should be a string literal" ; options.path
515+ end
516+ | _ -> options.path in
517+ let security_type, security = match security with
518+ | None -> options.security_type, options.security
519+ | Some e -> [% type : _], e in
520+ let options = {
521+ options with
522+ path; input; output;
523+ errors = Option. value ~default: options.errors errors;
524+ params = Option. value ~default: options.params params;
525+ section = Option. value ~default: options.section section;
526+ name = Option. value ~default: options.name name;
527+ descr = Option. value ~default: options.descr descr;
528+ security; security_type;
529+ register = Option. value ~default: [% expr false ] register;
530+ hide = Option. value ~default: options.hide hide;
531+ input_example = Option. value ~default: options.input_example input_example;
532+ output_example = Option. value ~default: options.output_example output_example;
533+ debug;
534+ } in
535+ let s, _, _ = service_value ~meth ~loc ~options ?name:sname (PStr [] ) in
536+ [ s ]
537+
538+ let derivers () =
539+ let open Ppxlib.Deriving in
540+ List. iter (fun meth ->
541+ let args_str = Args. (
542+ empty
543+ +> arg " path" __
544+ +> arg " input" __
545+ +> arg " output" __
546+ +> arg " errors" __
547+ +> arg " params" __
548+ +> arg " section" __
549+ +> arg " name" __
550+ +> arg " descr" __
551+ +> arg " security" __
552+ +> arg " register" __
553+ +> arg " hide" __
554+ +> arg " input_example" __
555+ +> arg " output_example" __
556+ +> flag " debug"
557+ ) in
558+ let str_type_decl = Generator. make args_str (deriver_str_gen meth) in
559+ ignore @@ add meth ~str_type_decl ) methods
0 commit comments