diff --git a/src/kernel_services/cmdline_parameters/parameter_builder.ml b/src/kernel_services/cmdline_parameters/parameter_builder.ml index 0403e08909b0f8bef41f2569955e593035555758..6997606429cfe4cfcbede1bf6b57a8e80259ef8f 100644 --- a/src/kernel_services/cmdline_parameters/parameter_builder.ml +++ b/src/kernel_services/cmdline_parameters/parameter_builder.ml @@ -534,6 +534,127 @@ struct let is_empty () = Filepath.Normalized.is_empty (get ()) end + (* ************************************************************************ *) + (** {3 Custom parameters} *) + (* ************************************************************************ *) + + module Custom + (X: sig + include Parameter_sig.Input_with_arg + include Datatype.S + val default: t + val of_string: string -> t option + val to_string: t -> string + end) = + struct + + include Build + (struct + include X + let default () = default + let functor_name = "Value" + end) + + let possible_values = ref [] + let set_possible_values s = possible_values := s + let get_possible_values () = !possible_values + + (* Same interface as current module but with t replaced with string *) + module String_parameter = + struct + let get () = + X.to_string (get ()) + + let set s = + match X.of_string s with + | Some x -> set x + | None -> + (* Error during conversion from string to t, abort *) + let help_text = + match !possible_values with + | [] -> "" + | l -> + Format.asprintf "@ Possible values are: %a" + (Pretty_utils.pp_list ~sep:",@ " Format.pp_print_string) l + in + P.L.abort "invalid input '%s' for option %s. %s" s name help_text + + let add_set_hook f = + let f' x1 x2 = f (X.to_string x1) (X.to_string x2) in + add_set_hook f' + + let add_update_hook f = + let f' x1 x2 = f (X.to_string x1) (X.to_string x2) in + add_update_hook f' + end + + let parameter = + let accessor = + let open String_parameter in + Typed_parameter.String ( + { get; set; add_set_hook; add_update_hook }, + get_possible_values) + in + let reconfigurable = is_parameter_reconfigurable stage in + let p = + Typed_parameter.create ~name ~help:X.help ~accessor + ~visible:is_visible ~reconfigurable ~is_set + in + add_parameter !Parameter_customize.group_ref stage p; + Cmdline.add_option option_name + ~argname:X.arg_name + ~help:X.help + ~visible:is_visible + ~ext_help:!Parameter_customize.optional_help_ref + ~plugin:P.shortname + ~group + stage + (Cmdline.String String_parameter.set); + Parameter_customize.reset (); + if is_dynamic then + Dynamic.register ~plugin:empty_string X.option_name Typed_parameter.ty p + else + p + end + + module Enum + (X: sig + include Parameter_sig.Input_with_arg + type t + val default: t + val all_values: t list + val to_string: t -> string + end) = + struct + module Custom_input = + struct + include Datatype.Make (struct + include Datatype.Serializable_undefined + let name = "Parameter_builder.Enum(" ^ X.option_name ^ ")" + type t = X.t + let copy x = x + let compare = Stdlib.compare + let equal = Datatype.from_compare + let reprs = X.all_values + end) + + include X + + let of_string = + let table = + List.to_seq X.all_values + |> Seq.map (fun x -> X.to_string x, x) + |> Hashtbl.of_seq + in + Hashtbl.find_opt table + end + + include Custom (Custom_input) + + let () = + set_possible_values (List.map X.to_string X.all_values) + end + (* ************************************************************************ *) (** {3 Collections} *) (* ************************************************************************ *) diff --git a/src/kernel_services/cmdline_parameters/parameter_sig.ml b/src/kernel_services/cmdline_parameters/parameter_sig.ml index 7cb76c39aeef211ed269d0a1533c8048a74700a4..e6f7335c2c0d1275724ce71a31168e9be132a242 100644 --- a/src/kernel_services/cmdline_parameters/parameter_sig.ml +++ b/src/kernel_services/cmdline_parameters/parameter_sig.ml @@ -279,6 +279,21 @@ module type String = sig *) end +(** Signature for a custom parameter. *) +module type Custom = sig + include S + + val set_possible_values: string list -> unit + (** Set what are the acceptable values for this parameter. + If the given list is empty, then all values are acceptable. + @since Frama-C+dev *) + + val get_possible_values: unit -> string list + (** What are the acceptable values for this parameter. + If the returned list is empty, then all values are acceptable. + @since Frama-C+dev *) +end + (* ************************************************************************** *) (** {3 Custom signatures} *) (* ************************************************************************** *) @@ -558,6 +573,28 @@ module type Builder = sig and vice-versa. *) end): Filepath + (** Allow using custom types as parameters. + @since Frama-c+dev *) + module Custom(X: sig + include Input_with_arg + include Datatype.S + val default: t + val of_string: string -> t option + val to_string: t -> string + end) : Custom with type t = X.t + + (** A fixed set of possible values, represented by a type [t], intended to be + a variant with only a finite number of possible constructions. + Note that [t] must be comparable using [Stdlib.compare]. + @since Frama-c+dev *) + module Enum(X : sig + include Input_with_arg + type t + val default: t + val all_values: t list + val to_string: t -> string + end) : S with type t = X.t + exception Cannot_build of string module Make_set (E: diff --git a/src/plugins/eva/engine/iterator.ml b/src/plugins/eva/engine/iterator.ml index 899fb60129901f150699afc38977f924bef104f0..f17c7e4f86e72193b7c2f989cd578e98f6aa784e 100644 --- a/src/plugins/eva/engine/iterator.ml +++ b/src/plugins/eva/engine/iterator.ml @@ -100,15 +100,6 @@ module Make_Dataflow (* --- Plugin parameters --- *) - type descending_strategy = NoIteration | FullIteration | ExitIteration - - let descending_iteration : descending_strategy = - match Parameters.DescendingIteration.get () with - | "no" -> NoIteration - | "exits" -> ExitIteration - | "full" -> FullIteration - | _ -> assert false - let hierachical_convergence : bool = Parameters.HierarchicalConvergence.get () @@ -584,7 +575,7 @@ module Make_Dataflow incr iteration_count; done; (* Descending sequence *) - let l = match descending_iteration with + let l = match Parameters.DescendingIteration.get () with | NoIteration -> [] | ExitIteration -> Self.debug ~dkey diff --git a/src/plugins/eva/parameters.ml b/src/plugins/eva/parameters.ml index 9900dd5cc70f953e69095e7a1a3e02c8453f7105..9f28b45413909c1f5fa636036d365b884c4b92e8 100644 --- a/src/plugins/eva/parameters.ml +++ b/src/plugins/eva/parameters.ml @@ -566,20 +566,27 @@ let () = add_correctness_dep InitializationPaddingGlobals.parameter (* --- Iteration strategy --- *) +type descending_strategy = NoIteration | FullIteration | ExitIteration + let () = Parameter_customize.set_group precision_tuning let () = Parameter_customize.is_invisible () module DescendingIteration = - String + Enum (struct - let default = "no" let option_name = "-eva-descending-iteration" let arg_name = "no|exits|full" let help = "Experimental. After hitting a postfix point, try to improve \ the precision with either a <full> iteration or an iteration \ from loop head to exit paths (<exits>) or do not try anything \ (<no>). Default is <no>." + type t = descending_strategy + let default = NoIteration + let all_values = [NoIteration ; FullIteration ; ExitIteration] + let to_string = function + | NoIteration -> "no" + | FullIteration -> "full" + | ExitIteration -> "exits" end) -let () = DescendingIteration.set_possible_values ["no" ; "exits" ; "full"] let () = add_precision_dep DescendingIteration.parameter let () = Parameter_customize.set_group precision_tuning diff --git a/src/plugins/eva/parameters.mli b/src/plugins/eva/parameters.mli index 7fa79238485ed73982558724e55d2687172c97ae..7c580cf947f83391e2eb898aa173fcbe1793f966 100644 --- a/src/plugins/eva/parameters.mli +++ b/src/plugins/eva/parameters.mli @@ -62,7 +62,9 @@ module WarnSignedConvertedDowncast: Parameter_sig.Bool module WarnPointerSubstraction: Parameter_sig.Bool module WarnCopyIndeterminate: Parameter_sig.Kernel_function_set -module DescendingIteration: Parameter_sig.String +type descending_strategy = NoIteration | FullIteration | ExitIteration + +module DescendingIteration: Parameter_sig.S with type t = descending_strategy module HierarchicalConvergence: Parameter_sig.Bool module WideningDelay: Parameter_sig.Int module WideningPeriod: Parameter_sig.Int