mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-23 21:33:49 +00:00
When switch detection looks at a disjunction, it loops over all the nonlocal variables that are already-bound on entry to the disjunction, to see whether the disjunction is a switch on that variable. We used to stop this search as soon as we found what looked like an good candidate, but in some rare cases, (a) committing to this candidate leads to a determinism that is not as tight as possible, and (b), if we chose to transform the disjunction into another candidate, the resulting determinism *would* be as tight as possible. The fix is to always gather all the candidate switches, rank them in order of how likely they are to yield a tight determinism, and choose the candidate with the highest rank. Doing this requires computing whether *each candidate switch* is a can_fail switch, whereas the old approach required computing only whether the *chosen switch* is a can_fail switch. While avoiding this small amount of extra computation was probably a good tradeoff in the mid 1990s, it isn't anymore. The new code is also simpler and clearer, for two distinct reasons. One is that committing to a good-enough candidate as soon as we find it required mixing the code that *finds* candidate switches with the code that *acts* on the selected candidate. The second is that the old code could choose the best possible switch (none of whose arms is reachable due the switched-on variable's initial inst, and which can therefore be translated to nothing more than just `fail') only by accident, never by design, since it tested which arms are reachable only *after* it has already selected the variable to switch on. This diff fixes Mantis bug #414. compiler/switch_detection.m: As above. tests/valid/bug414.m: The test case for the bug. tests/valid/Mmakefile: Enable the test case.
44 lines
1.2 KiB
Mathematica
44 lines
1.2 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2016 The Mercury Team
|
|
|
|
:- module bug414.
|
|
|
|
:- interface.
|
|
|
|
:- import_module string.
|
|
|
|
:- type loader.
|
|
|
|
:- func prefix_locator(loader) = string.
|
|
|
|
:- implementation.
|
|
|
|
:- type loader
|
|
---> loader(
|
|
loader_prefix :: string,
|
|
loader_replay_prefix :: string,
|
|
loader_replay_options :: replay_options
|
|
).
|
|
|
|
:- type replay_options
|
|
---> replay_none
|
|
; replay_save(string)
|
|
; replay_load(string).
|
|
|
|
prefix_locator(Loader) = Prefix :-
|
|
% Mercury is unable to properly detect the switch on Replay.
|
|
% It works if the a single deconstruction of Loader is made outside
|
|
% the switch and unfication-asignments inside the switch.
|
|
Replay = Loader ^ loader_replay_options,
|
|
(
|
|
( Replay = replay_none
|
|
; Replay = replay_save(_)
|
|
),
|
|
Prefix = Loader ^ loader_prefix
|
|
;
|
|
Replay = replay_load(_),
|
|
Prefix = Loader ^ loader_replay_prefix
|
|
).
|