Select generated operations without introducing hidden dependencies
This commit is contained in:
4 files changed
+64
-7
No files matched your search
@@ -20,6 +20,7 @@ test: all
|
|||||||
./runtime.byte
|
./runtime.byte
|
||||||
$(OCAMLC) -ppx ./rewrite fieldglass.cma record.ml -o record.byte
|
$(OCAMLC) -ppx ./rewrite fieldglass.cma record.ml -o record.byte
|
||||||
./record.byte
|
./record.byte
|
||||||
|
OCAMLC=$(OCAMLC) sh error.sh
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.cmi *.cmo *.cma *.byte rewrite
|
rm -f *.cmi *.cmo *.cma *.byte rewrite
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
directory=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$directory"' EXIT HUP INT TERM
|
||||||
|
|
||||||
|
reject() {
|
||||||
|
printf '%s\n' "$1" > "$directory/rejected.ml"
|
||||||
|
if "${OCAMLC:-ocamlc}" -ppx ./rewrite -c "$directory/rejected.ml" 2> "$directory/error"; then
|
||||||
|
echo "Unexpected compilation success: $1" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! grep -q "$2" "$directory/error"; then
|
||||||
|
cat "$directory/error" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
reject 'type t = { colour : string } [@@fieldglass generate ~no_get]
|
||||||
|
let _ = colour' 'Unbound value colour'
|
||||||
|
reject 'type t = { colour : string } [@@fieldglass generate ~no_set]
|
||||||
|
let _ = set_colour' 'Unbound value set_colour'
|
||||||
|
reject 'type t = { colour : string } [@@fieldglass generate ~no_update]
|
||||||
|
let _ = update_colour' 'Unbound value update_colour'
|
||||||
|
reject 'type t = { colour : string } [@@fieldglass generate ~no_lens]
|
||||||
|
let _ = _colour' 'Unbound value _colour'
|
||||||
|
reject 'type t = { colour : string } [@@fieldglass generate ~just_lens]
|
||||||
|
let _ = colour' 'Unbound value colour'
|
||||||
@@ -116,3 +116,20 @@ let () =
|
|||||||
assert (Fieldglass.set Ordered._count 2 Ordered.{ count = 1 } = Ordered.{ count = 2 });
|
assert (Fieldglass.set Ordered._count 2 Ordered.{ count = 1 } = Ordered.{ count = 2 });
|
||||||
assert (Positional.update_count Positional.{ count = 1 } succ = Positional.{ count = 2 });
|
assert (Positional.update_count Positional.{ count = 1 } succ = Positional.{ count = 2 });
|
||||||
assert (Last.update_count succ Last.{ count = 1 } = Last.{ count = 2 })
|
assert (Last.update_count succ Last.{ count = 1 } = Last.{ count = 2 })
|
||||||
|
|
||||||
|
module Pairs = struct
|
||||||
|
type t = { colour : string } [@@fieldglass generate ~just_lens]
|
||||||
|
end
|
||||||
|
|
||||||
|
module Silent = struct
|
||||||
|
type t = { colour : string } [@@fieldglass generate ~just_lens ~no_lens]
|
||||||
|
end
|
||||||
|
|
||||||
|
module Functions = struct
|
||||||
|
type t = { colour : string } [@@fieldglass generate ~no_lens ~no_get:false]
|
||||||
|
end
|
||||||
|
|
||||||
|
let () =
|
||||||
|
assert (Fieldglass.view Pairs._colour Pairs.{ colour = "grey" } = "grey");
|
||||||
|
assert (Silent.{ colour = "grey" }.colour = "grey");
|
||||||
|
assert (Functions.colour Functions.{ colour = "grey" } = "grey")
|
||||||
+19
-7
@@ -17,10 +17,15 @@ type options = {
|
|||||||
update_prefix : string;
|
update_prefix : string;
|
||||||
self_first : bool;
|
self_first : bool;
|
||||||
function_label : string option;
|
function_label : string option;
|
||||||
|
getters : bool;
|
||||||
|
setters : bool;
|
||||||
|
updaters : bool;
|
||||||
|
lenses : bool;
|
||||||
}
|
}
|
||||||
let defaults = { field_prefix = Plain; get_prefix = None;
|
let defaults = { field_prefix = Plain; get_prefix = None;
|
||||||
set_prefix = "set"; update_prefix = "update";
|
set_prefix = "set"; update_prefix = "update";
|
||||||
self_first = false; function_label = Some "f" }
|
self_first = false; function_label = Some "f";
|
||||||
|
getters = true; setters = true; updaters = true; lenses = true }
|
||||||
|
|
||||||
let word expression =
|
let word expression =
|
||||||
match expression.pexp_desc with
|
match expression.pexp_desc with
|
||||||
@@ -49,6 +54,13 @@ let configure options (label, expression) =
|
|||||||
| Labelled "func_named_arg" -> { options with function_label = Some (word expression) }
|
| Labelled "func_named_arg" -> { options with function_label = Some (word expression) }
|
||||||
| Labelled "func_no_named_arg" ->
|
| Labelled "func_no_named_arg" ->
|
||||||
{ options with function_label = if flag "func_no_named_arg" expression then None else Some "f" }
|
{ options with function_label = if flag "func_no_named_arg" expression then None else Some "f" }
|
||||||
|
| Labelled "no_get" -> { options with getters = not (flag "no_get" expression) }
|
||||||
|
| Labelled "no_set" -> { options with setters = not (flag "no_set" expression) }
|
||||||
|
| Labelled "no_update" -> { options with updaters = not (flag "no_update" expression) }
|
||||||
|
| Labelled "no_lens" -> { options with lenses = not (flag "no_lens" expression) }
|
||||||
|
| Labelled "just_lens" ->
|
||||||
|
let functions = not (flag "just_lens" expression) in
|
||||||
|
{ options with getters = functions; setters = functions; updaters = functions }
|
||||||
| _ -> Location.raise_errorf ~loc:expression.pexp_loc
|
| _ -> Location.raise_errorf ~loc:expression.pexp_loc
|
||||||
"fieldglass: unrecognised configuration option"
|
"fieldglass: unrecognised configuration option"
|
||||||
|
|
||||||
@@ -110,12 +122,12 @@ let generate options declaration =
|
|||||||
let updater = arguments options.self_first label "__fg_function"
|
let updater = arguments options.self_first label "__fg_function"
|
||||||
(replace (Exp.apply ~loc (value ~loc "__fg_function")
|
(replace (Exp.apply ~loc (value ~loc "__fg_function")
|
||||||
[Nolabel, Exp.field ~loc source (ident ~loc name)])) in
|
[Nolabel, Exp.field ~loc source (ident ~loc name)])) in
|
||||||
List.map (fun (name, body) ->
|
List.concat (List.map (fun (enabled, name, body) ->
|
||||||
Str.value ~loc Nonrecursive [Vb.mk ~loc (variable ~loc name) body])
|
if enabled then [Str.value ~loc Nonrecursive [Vb.mk ~loc (variable ~loc name) body]] else [])
|
||||||
[(match options.get_prefix with None -> short_name | Some prefix -> prefix ^ "_" ^ short_name), getter;
|
[options.getters, (match options.get_prefix with None -> short_name | Some prefix -> prefix ^ "_" ^ short_name), getter;
|
||||||
options.set_prefix ^ "_" ^ short_name, setter options.self_first;
|
options.setters, options.set_prefix ^ "_" ^ short_name, setter options.self_first;
|
||||||
options.update_prefix ^ "_" ^ short_name, updater;
|
options.updaters, options.update_prefix ^ "_" ^ short_name, updater;
|
||||||
"_" ^ short_name, Exp.tuple ~loc [getter; setter false]]) fields (field_names fields))
|
options.lenses, "_" ^ short_name, Exp.tuple ~loc [getter; setter false]])) fields (field_names fields))
|
||||||
|
|
||||||
let structure mapper items =
|
let structure mapper items =
|
||||||
List.concat (List.map (fun item ->
|
List.concat (List.map (fun item ->
|
||||||
|
|||||||
Reference in new issue
Block a user