[m-rev.] for review: split getopt*.m's work into three phases
Peter Wang
novalazy at gmail.com
Sat Jan 8 17:18:21 AEDT 2022
On Thu, 06 Jan 2022 16:51:16 +1100 "Zoltan Somogyi" <zoltan.somogyi at runbox.com> wrote:
>
> The new code in getopt_io.m uses cords to represent option values,
> because using reversed lists would be too complex in this application
> due to the fact they would have to mix with *unreversed* lists.
> On the other hand, we want to encode the invariant that expanding out
> file_special options leaves no file_special options in the option value list.
> This diff does that using insts, which requires cord operations that preserve
> insts. One consequence of this is that this diff exports the implementation
> type of cords, though not in the documented part of cord.m's interface.
> This is undesirable.
>
> I see two possible alternatives. First, we getopt*.m need only a very small
> part of cord.m's functionality, so we could bodily duplicate that part
> in getopt*.m, leaving cord.m unchanged. Second, we could use a subtype
> to record the absence of file_specials, instead of an inst. The latter would
> require a decision that subtypes are mature enough that we are willing
> to let the whole Mercury implementation break if they break. Opinions,
> especially from Peter on the last heading?
If you don't want to use subtypes yet, there's no *need* to encode the
invariant, as far as I can see. Just abort if process_options_values
sees a file_specials (which should be never). That's cleaner than
secretly exporting some stuff in cord.m.
>
> There will need to be entries in NEWS, but I want to hold off on that
> until we agree about yet another issue. The new predicates exported
> by getopt*.m have an argument that returns an error indication
> if an error was in fact seen, BUT, even if an error *was* seen, they
> do return other output as well, such as the list of option values
> seen before the error. Should this be the case?
I previously said "yes" (without any justification) so I'll say "yes"
again. I don't have any use case in mind.
> Should we instead return
> the non-error output *only* in the absence of an error? Having the
> non-error output up to the error may be useful to some callers,
> but do we want to commit to preserving the exact same non-error
> output in the presence of errors? This diff itself affects error behavior,
> in that before this diff, if an argument list had both a reference to a
> nonexistent option and a reference to an existing file_special option
> that named a nonexistent file, we used to report whichever came first
> on the command line, while after this diff, we will always report the
> nonexistent option.
Returning the first error does seem slightly more obvious but it's
unlikely anyone would ever notice the difference, or care.
> diff --git a/library/getopt_io.m b/library/getopt_io.m
> index bfefd70f2..c0da9a9bf 100644
> --- a/library/getopt_io.m
> +++ b/library/getopt_io.m
> @@ -126,6 +126,22 @@
>
> %---------------------------------------------------------------------------%
>
> +:- type short_option(OptionType) == (pred(char, OptionType)).
> +:- inst short_option == (pred(in, out) is semidet).
> +
> +:- type long_option(OptionType) == (pred(string, OptionType)).
> +:- inst long_option == (pred(in, out) is semidet).
> +
> +:- type option_defaul_value(OptionType) == (pred(OptionType, option_data)).
> +:- inst option_defaul_value_nondet == (pred(out, out) is nondet).
> +:- inst option_defaul_value_multi == (pred(out, out) is multi).
default
> +
> +:- type special_handler(OptionType) ==
> + (pred(OptionType, special_data,
> + option_table(OptionType), maybe_option_table(OptionType))).
> +:- inst special_handler ==
> + (pred(in, in, in, out) is semidet).
> +
Delete trailing whitespace.
> +%---------------------------------------------------------------------------%
> +
> + % An inst that lists all the function symbols of the option_value type
> + % *except* ov_file_special.
> +:- inst non_file_special for option_value/1
> + ---> ov_bool(ground, ground, ground)
> + ; ov_int(ground, ground, ground)
> + ; ov_string(ground, ground, ground)
> + ; ov_maybe_int(ground, ground, ground)
> + ; ov_maybe_string(ground, ground, ground)
> + ; ov_accumulating(ground, ground, ground)
> + ; ov_accumulating_reset(ground, ground)
> + ; ov_special(ground, ground)
> + ; ov_bool_special(ground, ground, ground)
> + ; ov_int_special(ground, ground, ground)
> + ; ov_string_special(ground, ground, ground)
> + ; ov_maybe_string_special(ground, ground, ground).
> +
> + % expand_file_specials(OptionOps, OptionTable, OptionValues,
> + % MaybeError, NonFileSpecialOptionValues, !MaybeIO):
Delete trailing space.
The rest looks okay.
Peter
More information about the reviews
mailing list