Disambiguate recursive record groups and share group configuration
This commit is contained in:
2 files changed
+35
-9
No files matched your search
@@ -133,3 +133,24 @@ let () =
|
|||||||
assert (Fieldglass.view Pairs._colour Pairs.{ colour = "grey" } = "grey");
|
assert (Fieldglass.view Pairs._colour Pairs.{ colour = "grey" } = "grey");
|
||||||
assert (Silent.{ colour = "grey" }.colour = "grey");
|
assert (Silent.{ colour = "grey" }.colour = "grey");
|
||||||
assert (Functions.colour Functions.{ colour = "grey" } = "grey")
|
assert (Functions.colour Functions.{ colour = "grey" } = "grey")
|
||||||
|
|
||||||
|
module Recursive = struct
|
||||||
|
type left = { value : int; next : right option }
|
||||||
|
and right = { value : string; next : left option }
|
||||||
|
[@@fieldglass generate ~field_prefix_from_type]
|
||||||
|
end
|
||||||
|
|
||||||
|
module Ambiguous = struct
|
||||||
|
type number = { contents : int }
|
||||||
|
and text = { contents : string }
|
||||||
|
[@@fieldglass generate ~field_prefix_from_type]
|
||||||
|
end
|
||||||
|
|
||||||
|
let () =
|
||||||
|
let left : Recursive.left = { value = 3; next = None } in
|
||||||
|
let right : Recursive.right = { value = "grey"; next = Some left } in
|
||||||
|
assert (Recursive.left_value left = 3);
|
||||||
|
assert (Recursive.right_value (Recursive.set_right_value "blue" right) = "blue");
|
||||||
|
assert (Recursive.right_next right = Some left);
|
||||||
|
let number : Ambiguous.number = { contents = 3 } in
|
||||||
|
assert (Ambiguous.number_contents (Ambiguous.set_number_contents 4 number) = 4)
|
||||||
+14
-9
@@ -73,7 +73,7 @@ let configured declaration =
|
|||||||
| Pexp_apply ({ pexp_desc = Pexp_ident { txt = Longident.Lident "generate"; _ }; _ }, arguments) -> arguments
|
| Pexp_apply ({ pexp_desc = Pexp_ident { txt = Longident.Lident "generate"; _ }; _ }, arguments) -> arguments
|
||||||
| _ -> Location.raise_errorf ~loc:expression.pexp_loc
|
| _ -> Location.raise_errorf ~loc:expression.pexp_loc
|
||||||
"fieldglass: expected generate followed by labelled options" in
|
"fieldglass: expected generate followed by labelled options" in
|
||||||
Some (List.fold_left configure defaults arguments)
|
Some arguments
|
||||||
| _ -> Location.raise_errorf ~loc:declaration.ptype_loc
|
| _ -> Location.raise_errorf ~loc:declaration.ptype_loc
|
||||||
"fieldglass: expected [@@fieldglass generate]"
|
"fieldglass: expected [@@fieldglass generate]"
|
||||||
|
|
||||||
@@ -99,9 +99,10 @@ let generate options declaration =
|
|||||||
| _ -> Location.raise_errorf ~loc "fieldglass: expected a record type"
|
| _ -> Location.raise_errorf ~loc "fieldglass: expected a record type"
|
||||||
in
|
in
|
||||||
let source = value ~loc "__fg_source" in
|
let source = value ~loc "__fg_source" in
|
||||||
|
let record_type () = Typ.constr ~loc (ident ~loc declaration.ptype_name.txt)
|
||||||
|
(List.map (fun _ -> Typ.any ~loc ()) declaration.ptype_params) in
|
||||||
let source_pattern = Pat.constraint_ ~loc (variable ~loc "__fg_source")
|
let source_pattern = Pat.constraint_ ~loc (variable ~loc "__fg_source")
|
||||||
(Typ.constr ~loc (ident ~loc declaration.ptype_name.txt)
|
(record_type ()) in
|
||||||
(List.map (fun _ -> Typ.any ~loc ()) declaration.ptype_params)) in
|
|
||||||
let arguments self_first label name body =
|
let arguments self_first label name body =
|
||||||
let self = lambda ~loc Nolabel source_pattern in
|
let self = lambda ~loc Nolabel source_pattern in
|
||||||
let other = lambda ~loc label (variable ~loc name) in
|
let other = lambda ~loc label (variable ~loc name) in
|
||||||
@@ -114,8 +115,9 @@ let generate options declaration =
|
|||||||
| Type_name -> declaration.ptype_name.txt ^ "_" ^ short_name in
|
| Type_name -> declaration.ptype_name.txt ^ "_" ^ short_name in
|
||||||
let getter = lambda ~loc Nolabel source_pattern
|
let getter = lambda ~loc Nolabel source_pattern
|
||||||
(Exp.field ~loc source (ident ~loc name)) in
|
(Exp.field ~loc source (ident ~loc name)) in
|
||||||
let replace expression = Exp.record ~loc [ident ~loc name, expression]
|
let replace expression = Exp.constraint_ ~loc
|
||||||
(if List.length fields = 1 then None else Some source) in
|
(Exp.record ~loc [ident ~loc name, expression]
|
||||||
|
(if List.length fields = 1 then None else Some source)) (record_type ()) in
|
||||||
let setter self_first = arguments self_first Nolabel "__fg_value"
|
let setter self_first = arguments self_first Nolabel "__fg_value"
|
||||||
(replace (value ~loc "__fg_value")) in
|
(replace (value ~loc "__fg_value")) in
|
||||||
let label = match options.function_label with None -> Nolabel | Some name -> Labelled name in
|
let label = match options.function_label with None -> Nolabel | Some name -> Labelled name in
|
||||||
@@ -134,10 +136,13 @@ let structure mapper items =
|
|||||||
let item = Ast_mapper.default_mapper.structure_item mapper item in
|
let item = Ast_mapper.default_mapper.structure_item mapper item in
|
||||||
match item.pstr_desc with
|
match item.pstr_desc with
|
||||||
| Pstr_type (recursive, declarations) ->
|
| Pstr_type (recursive, declarations) ->
|
||||||
let generated = List.concat (List.map (fun declaration ->
|
let configurations = List.map configured declarations in
|
||||||
match configured declaration with
|
let generated =
|
||||||
| Some options -> generate options declaration
|
if List.exists (function Some _ -> true | None -> false) configurations then
|
||||||
| None -> []) declarations) in
|
let arguments = List.concat (List.map (function Some args -> args | None -> []) configurations) in
|
||||||
|
let options = List.fold_left configure defaults arguments in
|
||||||
|
List.concat (List.map (generate options) declarations)
|
||||||
|
else [] in
|
||||||
let declarations = List.map (fun declaration ->
|
let declarations = List.map (fun declaration ->
|
||||||
{ declaration with ptype_attributes =
|
{ declaration with ptype_attributes =
|
||||||
List.filter (fun attribute -> not (is_marker attribute)) declaration.ptype_attributes }) declarations in
|
List.filter (fun attribute -> not (is_marker attribute)) declaration.ptype_attributes }) declarations in
|
||||||
|
|||||||
Reference in new issue
Block a user