@@ -45,29 +45,19 @@ type options = {
45
45
service : expression option ;
46
46
}
47
47
48
- let empty ~loc = pexp_construct ~loc (llid ~loc " EzAPI.Empty" ) None
49
48
let raw e =
50
49
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];
71
61
debug = false ; directory = None ; service = None
72
62
}
73
63
@@ -100,23 +90,22 @@ let string_literal = function
100
90
| Ppxlib. Pconst_string (s , _ , _ ) -> Some s
101
91
| _ -> None
102
92
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 =
105
94
match p with
106
95
| PStr [ {pstr_desc= Pstr_eval ({pexp_desc= Pexp_record (l, _); _}, _); _} ] ->
107
96
let l = List. filter_map (function ({txt =Lident s ; loc} , e ) -> Some (s, loc, e) | _ -> None ) l in
108
97
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
110
99
| Pexp_constant cst ->
111
100
begin match string_literal cst with
112
101
| Some s -> name, { acc with path = parse_path ~loc: e.pexp_loc s }
113
102
| _ -> Format. eprintf " path should be a string literal" ; name, acc
114
103
end
115
104
| _ -> Format. eprintf " path should be a literal" ; name, acc
116
105
end
117
- | "input" -> name, { acc with input = json e }
106
+ | "input" -> name, { acc with input = [ % expr EzAPI. Json [ % e e]] }
118
107
| "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]] }
120
109
| "raw_output" -> name, { acc with output = raw e }
121
110
| "params" -> name, { acc with params = esome e }
122
111
| "errors" -> name, { acc with errors = esome e; error_type = ptyp_any ~loc }
@@ -130,8 +119,9 @@ let get_options ~loc ?name ?(client=false) p =
130
119
| _ -> Format. eprintf " name should be a string literal" ; name, acc
131
120
end
132
121
| _ ->
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
135
125
end
136
126
| "descr" -> name, { acc with descr = esome e }
137
127
| "security" -> name, { acc with security = esome e; security_type = ptyp_any ~loc }
@@ -150,20 +140,21 @@ let get_options ~loc ?name ?(client=false) p =
150
140
end
151
141
| "service" ->
152
142
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
154
144
| 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 }
157
148
| PStr s ->
158
149
Format. eprintf " attribute not understood %a@." Pprintast. structure s;
159
- name, options ?register ?name loc
150
+ name, options
160
151
| _ ->
161
152
Format. eprintf " attribute not understood@." ;
162
- name, options ?register ?name loc
153
+ name, options
163
154
164
- let service_value ?name ?client ~meth ~loc p =
155
+ let service_value ?name ?options ~meth ~loc p =
165
156
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
167
158
match name with
168
159
| None -> Location. raise_errorf ~loc " service doesn't have a name"
169
160
| Some name ->
@@ -344,6 +335,8 @@ let server ~loc p =
344
335
[% expr EzLwtSys. run (fun () -> [% e server_aux e])]
345
336
| _ -> Location. raise_errorf ~loc " server options not understood"
346
337
338
+ (* * main mapper *)
339
+
347
340
let deprecate =
348
341
let t : (string, unit) Hashtbl.t = Hashtbl. create 10 in
349
342
fun s ->
@@ -442,14 +435,52 @@ let transform ?kind () =
442
435
(* client service *)
443
436
| Pstr_attribute a when List. mem a.attr_name.txt methods ->
444
437
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
446
441
service :: acc
447
442
| 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
449
445
service :: acc
450
446
| 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
452
449
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
453
484
| _ -> (self#structure_item it) :: acc
454
485
) [] str
455
486
@@ -460,3 +491,69 @@ let transform ?kind () =
460
491
end
461
492
462
493
let 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