mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-20 16:31:04 +00:00
Specifically, we now do three new checks:
BAD_DETISM: We now generate error messages for predicate declarations
that specify a determinism without also specifying argument modes.
BAD_PREDMODE: We now generate error messages for standalone mode declarations
for predicates whose predicate declaration includes modes for the arguments.
BAD_MODE_SECTION: We now generate error messages for standalone mode
declarations that are not in the same section as the predicate's (or
function's) type declaration.
compiler/hlds_pred.m:
Add a slot to the pred_sub_info. If the predicate is explicitly defined by
the user in the current module, this contains the id of the section that
contains its predicate declaration (for the BAD_MODE_SECTION check)
and whether that predicate declaration also had modes for the arguments
(for the BAD_PREDMODE check).
compiler/add_pred.m:
When adding adding new predicate declarations, perform the BAD_DETISM
check, and record the info needed for the BAD_PREDMODE and BAD_MODE_SECTION
checks.
When adding adding new mode declarations, perform the BAD_PREDMODE
and BAD_MODE_SECTION checks.
compiler/add_class.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_solver.m:
compiler/add_special_pred.m:
compiler/check_typeclass.m:
compiler/dep_par_conj.m:
compiler/higher_order.m:
compiler/make_hlds_passes.m:
compiler/table_gen.m:
compiler/unused_args.m:
Conform to the changes above.
mdbcomp/builtin_modules.m:
Add a utility predicate for use by new code in add_pred.m.
compiler/comp_unit_interface.m:
compiler/goal_util.m:
compiler/prog_rename.m:
compiler/quantification.m:
deep_profiler/program_representation_utils.m:
library/calendar.m:
library/mutvar.m:
library/pretty_printer.m:
library/random.m:
library/set_ctree234.m:
library/solutions.m:
library/stream.string_writer.m:
profiler/globals.m:
tests/accumulator/nonrec.m:
tests/accumulator/out_to_in.m:
tests/declarative_debugging/library_forwarding.m:
tests/dppd/applast_impl.m:
tests/dppd/grammar_impl.m:
tests/dppd/regexp.m:
tests/dppd/transpose_impl.m:
tests/hard_coded/copy_pred.m:
tests/hard_coded/ho_func_default_inst.m:
tests/recompilation/unchanged_pred_nr_2.m.1:
tests/recompilation/unchanged_pred_nr_2.m.2:
tests/valid/det_switch.m:
tests/valid/inlining_bug.m:
Delete determinism declarations from predicate and function declarations
that have no argument mode information, since the BAD_DETISM check
now makes these errors.
tests/valid/two_pragma_c_codes.m:
Move some mode declarations to the right section, since the
BAD_MODE_SECTION check now generates an error for the old code.
tests/invalid/typeclass_bad_method_mode.{m,err_exp}:
New test case to test for the BAD_PREDMODE check.
tests/invalid/mode_decl_in_wrong_section.{m,err_exp}:
New test case to test for the BAD_MODE_SECTION check.
tests/invalid/bad_detism.err_exp:
Add an expected output for this old, but never enabled test case,
which tests for new check BAD_DETISM.
tests/invalid/Mmakefile:
Enable the new test cases.
tests/invalid/typeclass_dup_method_mode.m:
This test case used to have two bugs. One is now by itself in the new
typeclass_bad_method_mode.m test case, so modify it to contain only
the other (indistinguishable modes).
tests/invalid/func_errors.err_exp:
tests/invalid/tc_err1.err_exp:
tests/invalid/undef_lambda_mode.err_exp:
tests/invalid/undef_type_mode_qual.err_exp:
Expect an extra error message from the BAD_DETISM check.
160 lines
6.2 KiB
Mathematica
160 lines
6.2 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1996-2012 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% The predicates here are similar to the "apply_variable_renaming" family of
|
|
% predicates in library/term.m, but they allow the caller to specify that all
|
|
% variables in the data structure being updated must appear in the renaming.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module parse_tree.prog_rename.
|
|
|
|
:- interface.
|
|
|
|
:- import_module parse_tree.set_of_var.
|
|
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module set.
|
|
:- import_module term.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type must_rename
|
|
---> must_rename
|
|
; need_not_rename.
|
|
|
|
:- inst must_rename
|
|
---> must_rename.
|
|
:- inst need_not_rename
|
|
---> need_not_rename.
|
|
|
|
:- pred rename_vars_in_term(must_rename, map(var(V), var(V)),
|
|
term(V), term(V)).
|
|
:- mode rename_vars_in_term(in(must_rename), in, in, out) is det.
|
|
:- mode rename_vars_in_term(in(need_not_rename), in, in, out) is det.
|
|
:- mode rename_vars_in_term(in, in, in, out) is det.
|
|
|
|
:- pred rename_vars_in_term_list(must_rename, map(var(V), var(V)),
|
|
list(term(V)), list(term(V))).
|
|
:- mode rename_vars_in_term_list(in(must_rename), in, in, out) is det.
|
|
:- mode rename_vars_in_term_list(in(need_not_rename), in, in, out) is det.
|
|
:- mode rename_vars_in_term_list(in, in, in, out) is det.
|
|
|
|
:- pred rename_vars_in_var_set(must_rename, map(var(V), var(V)),
|
|
set(var(V)), set(var(V))).
|
|
:- mode rename_vars_in_var_set(in(must_rename), in, in, out) is det.
|
|
:- mode rename_vars_in_var_set(in(need_not_rename), in, in, out) is det.
|
|
:- mode rename_vars_in_var_set(in, in, in, out) is det.
|
|
|
|
:- pred rename_vars_in_set_of_var(must_rename, map(var(V), var(V)),
|
|
set_of_var(V), set_of_var(V)).
|
|
:- mode rename_vars_in_set_of_var(in(must_rename), in, in, out) is det.
|
|
:- mode rename_vars_in_set_of_var(in(need_not_rename), in, in, out) is det.
|
|
:- mode rename_vars_in_set_of_var(in, in, in, out) is det.
|
|
|
|
:- pred rename_var_list(must_rename, map(var(V), var(V)),
|
|
list(var(V)), list(var(V))).
|
|
:- mode rename_var_list(in(must_rename), in, in, out) is det.
|
|
:- mode rename_var_list(in(need_not_rename), in, in, out) is det.
|
|
:- mode rename_var_list(in, in, in, out) is det.
|
|
|
|
:- pred rename_var(must_rename, map(var(V), var(V)),
|
|
var(V), var(V)).
|
|
:- mode rename_var(in(must_rename), in, in, out) is det.
|
|
:- mode rename_var(in(need_not_rename), in, in, out) is det.
|
|
:- mode rename_var(in, in, in, out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module require.
|
|
:- import_module string.
|
|
|
|
rename_vars_in_term(Must, Renaming, Term0, Term) :-
|
|
(
|
|
Term0 = variable(Var0, Context),
|
|
rename_var(Must, Renaming, Var0, Var),
|
|
Term = variable(Var, Context)
|
|
;
|
|
Term0 = functor(ConsId, Args0, Context),
|
|
% The mutual non-tail recursion between rename_vars_in_term and
|
|
% rename_vars_in_term_list means that when given a large Term0,
|
|
% this predicate may need a LOT of stack frames, and may even run
|
|
% the program out of stack.
|
|
%
|
|
% To try to prevent this in as many cases as possible (though
|
|
% unfortunately not all), we handle the first three arguments
|
|
% directly. The most common kind of very large term is a very
|
|
% long list, and with this approach, we use only one stack frame
|
|
% per list element, not two.
|
|
(
|
|
Args0 = [],
|
|
Args = []
|
|
;
|
|
Args0 = [Arg1Term0],
|
|
rename_vars_in_term(Must, Renaming, Arg1Term0, Arg1Term),
|
|
Args = [Arg1Term]
|
|
;
|
|
Args0 = [Arg1Term0, Arg2Term0],
|
|
rename_vars_in_term(Must, Renaming, Arg1Term0, Arg1Term),
|
|
rename_vars_in_term(Must, Renaming, Arg2Term0, Arg2Term),
|
|
Args = [Arg1Term, Arg2Term]
|
|
;
|
|
Args0 = [Arg1Term0, Arg2Term0, Arg3Term0 | OtherArgTerms0],
|
|
rename_vars_in_term(Must, Renaming, Arg1Term0, Arg1Term),
|
|
rename_vars_in_term(Must, Renaming, Arg2Term0, Arg2Term),
|
|
rename_vars_in_term(Must, Renaming, Arg3Term0, Arg3Term),
|
|
rename_vars_in_term_list(Must, Renaming,
|
|
OtherArgTerms0, OtherArgTerms),
|
|
Args = [Arg1Term, Arg2Term, Arg3Term | OtherArgTerms]
|
|
),
|
|
Term = functor(ConsId, Args, Context)
|
|
).
|
|
|
|
rename_vars_in_term_list(_Must, _Renaming, [], []).
|
|
rename_vars_in_term_list(Must, Renaming, [Term0 | Terms0], [Term | Terms]) :-
|
|
rename_vars_in_term(Must, Renaming, Term0, Term),
|
|
rename_vars_in_term_list(Must, Renaming, Terms0, Terms).
|
|
|
|
rename_vars_in_var_set(Must, Renaming, Vars0, Vars) :-
|
|
set.to_sorted_list(Vars0, VarsList0),
|
|
rename_var_list(Must, Renaming, VarsList0, VarsList),
|
|
set.list_to_set(VarsList, Vars).
|
|
|
|
rename_vars_in_set_of_var(Must, Renaming, Vars0, Vars) :-
|
|
set_of_var.to_sorted_list(Vars0, VarsList0),
|
|
rename_var_list(Must, Renaming, VarsList0, VarsList),
|
|
set_of_var.list_to_set(VarsList, Vars).
|
|
|
|
rename_var_list(_Must, _Renaming, [], []).
|
|
rename_var_list(Must, Renaming, [Var0 | Vars0], [Var | Vars]) :-
|
|
rename_var(Must, Renaming, Var0, Var),
|
|
rename_var_list(Must, Renaming, Vars0, Vars).
|
|
|
|
rename_var(Must, Renaming, Var0, Var) :-
|
|
( if map.search(Renaming, Var0, VarPrime) then
|
|
Var = VarPrime
|
|
else
|
|
(
|
|
Must = need_not_rename,
|
|
Var = Var0
|
|
;
|
|
Must = must_rename,
|
|
term.var_to_int(Var0, Var0Int),
|
|
string.format("rename_var: no substitute for var %i", [i(Var0Int)],
|
|
Msg),
|
|
unexpected($module, $pred, Msg)
|
|
)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module parse_tree.prog_rename.
|
|
%---------------------------------------------------------------------------%
|