The new construct looks like this:
require_switch_arms_det [C] (
(
C = 'a',
... compute Out ...
;
C = 'b',
... compute Out ...
)
)
If any of the goals computing Out are not det, the compiler will generate
an error message. The det at the end of the keyword can be replaced
by any of the other seven determinisms, though I don't think either
require_switch_arms_failure or require_switch_arms_erroneous will see much use.
This diff adds only the implementation. I will add the documentation
and the NEWS item after we all had a chance to install this diff and
try it out.
compiler/hlds_goal.m:
Add a scope representing this kind of goal in the HLDS.
compiler/prog_item.m:
Add a goal expression for this kind of goal in the parse tree.
compiler/prog_io_goal.m:
Look for the new kind of goal expression in terms when creating
the parse tree.
Factor out some commonalities between the parsing of the new goal
expression and existing types of goal expressions.
compiler/goal_expr_to_goal.m:
Convert the new kind of goal expression to the new scope in the HLDS.
compiler/det_report.m:
Implement the checks that the new goal type calls for.
Factor out some commonalities between the implementation of the new goal
type and existing goal types.
Move the types and predicates dealing with comparisons of determinisms
from here to prog_data.m, due to the sort-of-bugfix to modecheck_call.m.
compiler/prog_data.m:
Move the types and predicates dealing with comparisons of determinisms
from det_report.m to here. The old code for this was intended for only one
requirement, and did not deal well with comparisons of two determinisms
in which each determinism makes an assertion the other does not make.
Create a way to represent such comparison results.
compiler/modecheck_call.m:
When deciding which mode of a procedure to call, we prefer determinisms
that make more assertions about solution counts. However, when comparing
incomparable determinisms (such as semidet vs multi, each of which makes
an assertion the other doesn't), the algorithm chose based solely
on the ORDER of the modes. We now explicitly prefer modes that promise
lower maximum solution counts, giving less importance to cannot_fail
assertions.
compiler/*.m:
Conform to the change to hlds_goal.m or prog_item.m.
library/ops.m:
Add the new keywords as operators.
tests/hard_coded/require_scopes.{m,exp}:
Extend this test case to test the new construct in the absence of errors.
tests/invalid/require_scopes.{m,exp}:
Extend this test case to test the new construct in the presence of errors.
Estimated hours taken: 12
Branches: main
Add two new kinds of scopes to the language: one that requires the goal inside
the scope to have a given determinism, and one that requires it
to be complete, i.e. to have arms for all the function symbols in the type of
the switched-on variable.
The first kind of scope adds the keywords
require_det require_semidet
require_multi require_nondet
require_cc_multi require_cc_nondet
require_erroneous require_failure
to the language. They are intended to be used like this:
test_detism_scope(A, !IO) :-
(
A > 10,
require_det (
B = A * 2,
C = B mod 3
),
C = 1
->
X = C
;
X = A
),
io.format("test_detism_scope(%d) = %d\n", [i(A), i(X)], !IO).
The second kind of scope adds the keyword require_complete_switch to
the language. They are intended to be used like this:
do_test_switch_scope(A, X) :-
require_complete_switch [A] (
(
A = f1,
fail
;
A = f2,
( X = 1
; X = 2
)
;
A = f3(B),
( X = 3
; X = B
; X = B + 1
)
)
).
NEWS:
Announce the new scopes.
doc/reference_manual.texi:
Document the new scopes.
library/ops.m:
Add the new keywords as operators.
compiler/hlds_goal.m:
Add the new kinds of scopes to the HLDS.
compiler/prog_item.m:
Add the new kinds of scopes to the parse tree type.
compiler/prog_io_goal.m:
Recognize the new keywords. When we find a term with one of these
keywords as the function symbol, generate the corresponding parse tree
goal expression.
compiler/add_clause.m:
Convert these goal expressions to HLDS.
compiler/simplify.m:
Check the requirements expressed by the new scopes. If the requirement
is met, delete the scope wrapper. If the requirement is not met,
generate an error message and then delete the scope wrapper.
compiler/error_util.m:
Add a new format_component, words_qoute, which is like quote, but
yields words, not fixed, after quoting.
compiler/constraint.m:
compiler/det_analysis.m:
compiler/erl_code_gen.m:
compiler/goal_util.m:
compiler/hlds_desc.m:
compiler/hlds_out_goal.m:
compiler/interval.m:
compiler/lambda.m:
compiler/make_hlds_warn.m:
compiler/mercury_to_mercury.m:
compiler/mode_errors.m:
compiler/modecheck_goal.m:
compiler/module_imports.m:
compiler/module_qual.m:
compiler/polymorphism.m:
compiler/prog_util.m:
compiler/purity.m:
compiler/quantification.m:
compiler/saved_vars.m:
compiler/stm_expand.m:
compiler/try_expand.m:
compiler/typecheck.m:
Conform to the changes to the parse tree and HLDS goal types.
In one module, take advantage of the new format_component.
tests/hard_coded/require_scopes.{m,exp}:
A new test case to test the handling of the new scopes when their
requirements are met.
tests/hard_coded/Mmakefile:
Add the new test.
tests/invalid/require_scopes.{m,err_exp}:
A new test case to test the handling of the new scopes when their
requirements are NOT met.
tests/invalid/Mmakefile:
Add the new test.