The improvements take two forms.
The first is that when the mode checker tries to schedule a unification
of the form X = curried_pred(A1, ... An), but fails, perhaps because
curried_pred has more than one declared mode matching the current insts
of the Ai, we record this fact in the mode_info. Then, if later we find
that X is insufficiently instantiated, we print the message we originally
generated for the X = curried_pred(A1, ... An) unification (but which we
threw away when the scheduling attempt failed) as a possible explanation
of this insufficient instantiation.
The second is that when scheduling X = curried_pred(A1, ... An) but fails,
we record more information about the reason, to print it later in the hope that
it may help the user diagnose the problem.
compiler/mode_errors.m:
Change the representation of the errors resulting for not being able
to schedule rhs_lambda unifications of the form X = curried_pred(Ai).
Merge the previous two separate errors into one, and add a parameter
that that distinguishes the three (not two) possible different causes
of the error. Print better diagnostics for all three, based on a common
template.
Change the representation of the errors that say a variable is not
sufficiently instantiated, to make it possible (but of course not
compulsory) to record what error of the X = curried_pred(Ai) kind
may be responsible for it. Include the error message for this cause
in the error message about the insufficiently instantiated variable.
compiler/mode_info.m:
Add a field to the mode_info that allows a failed attempt to schedule
X = curried_pred(Ai) to record the error it generates as a possible
cause of the later insufficient instantiation of X.
compiler/modecheck_unify.m:
Gather the extra information now needed by the representation of mode
errors for failed attempts to schedule X = curried_pred(Ai).
Record the errors for such attempts in the new mode_info field.
compiler/modecheck_util.m:
When generating "variable is not sufficiently instantiated" errors,
see if the new mode_info field say that the insufficiently instantiated
variable was, in a previous conjunct, involved in a failed
X = curried_pred(Ai) unification, and if yes, record this fact
as a possible cause of the error.
compiler/modecheck_goal.m:
Reset the new field at the start of every branched control structure,
to prevent us from using information about X = curried_pred(Ai)
unifications in one branch in other, parallel branches.
Avoid allocating a context at every goal.
library/term.m:
Add a utility predicate to enable that avoidance.
NEWS:
Mention the new utility predicate.
Fix some no-longer-valid entries.
compiler/modecheck_call.m:
Make some code need less stack space.
Fix some comments.
compiler/modecheck_conj.m:
Clarify some code.
tests/invalid/uint_bitwise_xor_mode.{m,err_exp}:
A new test case for both improvements. It is a version of
tests/hard_coded/uint_bitwise.m cut down to contain just the bug
that previously we generate only a misleading error message for.
tests/invalid/Mmakefile:
Enable the new test.
tests/invalid/multimode_addr_problems.err_exp:
Update this expected output to account for the second improvement.
tests/invalid/*.{m,err_exp}:
tests/misc_tests/*.m:
tests/mmc_make/*.m:
tests/par_conj/*.m:
tests/purity/*.m:
tests/stm/*.m:
tests/string_format/*.m:
tests/structure_reuse/*.m:
tests/submodules/*.m:
tests/tabling/*.m:
tests/term/*.m:
tests/trailing/*.m:
tests/typeclasses/*.m:
tests/valid/*.m:
tests/warnings/*.{m,exp}:
Make these tests use four-space indentation, and ensure that
each module is imported on its own line. (I intend to use the latter
to figure out which subdirectories' tests can be executed in parallel.)
These changes usually move code to different lines. For the tests
that check compiler error messages, expect the new line numbers.
browser/cterm.m:
browser/tree234_cc.m:
Import only one module per line.
tests/hard_coded/boyer.m:
Fix something I missed.
Estimated hours taken: 15
Branches: main
Support currying of multi-moded predicates or functions when the mode to curry
can be determined from the insts of the higher-order arguments. e.g.
mymap(P, L0, L) :-
map(wrap(P), L0, L).
:- pred wrap(...).
:- mode wrap(in(pred(...) is det), ...) is det.
:- mode wrap(in(pred(...) is cc_multi, ...) is cc_multi.
...
compiler/post_typecheck.m:
Don't abort immediately on taking the address of a multi-moded
predicate. Leave the proc_id as invalid_proc_id and handle that
in polymorphism.m.
compiler/polymorphism.m:
Convert higher order terms to lambda goals even if the proc_id is
invalid (as above) moded by arbitrarily using the first mode. Then
polymorphism can proceed as usual. Mark the goals with feature
`feature_lambda_undetermined_mode', which tells mode checking to
handle it.
Add a predicate to fix up such lambda goals once mode checking does
figure out which mode should be called.
compiler/modecheck_unify.m:
compiler/mode_errors.m:
Handle goals with the `feature_lambda_undetermined_mode'. Try to
select a unique mode for the curried predicate then fix up the lambda
goal.
compiler/hlds_goal.m:
compiler/saved_vars.m:
Add `feature_lambda_undetermined_mode'.
compiler/goal_util.m:
Add a predicate to return all the pred_ids called in a goal
with the associated argument variables.
NEWS:
doc/reference_manual.texi:
Document and announce the change.
tests/hard_coded/Mmakefile:
tests/hard_coded/multimode_addr.exp:
tests/hard_coded/multimode_addr.m:
tests/invalid/Mmakefile:
tests/invalid/multimode_addr_problems.err_exp:
tests/invalid/multimode_addr_problems.m:
Add tests.