mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 09:53:36 +00:00
One option, --warn-non-contiguous-decls, generates warnings if the
mode declarations of a predicate or function aren't in a contiguous block
immediately following the pred or func declaration. Since this is a rare
kind of "style error", this option is enabled by default.
Two options, --warn-inconsistent-pred-order-clauses and
--warn-inconsistent-pred-order-foreign-procs, warn about inconsistencies
between (a) the order in which predicates (and functions) are declared,
and (b) the order in which they are defined. The two options differ in
their scope. The latter applies to all predicates and functions defined
in the module, while the former applies only to those whose definitions
include Mercury clauses.
Since an exported predicate or function may need nonexported auxiliary
predicates and/or functions, imposing a single order the declarations and
definitions of *all* the predicates and functions in a module is not a good
idea. Instead, both options divide the predicates and functions defined
in a module two groups, the exported and the nonexported, and expect
a consistent order only within each group.
The result is output that looks like this:
time.m:021: Warning: the order of the declarations and definitions of the
time.m:021: exported predicates is inconsistent, as shown by this diff:
time.m:021:
time.m:021: --- declaration order
time.m:021: +++ definition order
time.m:021: @@ -1,7 +1,7 @@
time.m:021: predicate `clock'/3
time.m:021: -predicate `time'/3
time.m:021: predicate `times'/4
time.m:021: function `clk_tck'/0
time.m:021: +predicate `time'/3
time.m:021: function `difftime'/2
time.m:021: predicate `localtime'/4
time.m:021: function `localtime'/1
compiler/options.m:
doc/user_guide.texi:
Add the new options.
compiler/style_checks.m:
A new module that generates the new warnings if warranted.
compiler/check_hlds.m:
compiler/notes/compiler_design.html:
Include and document the new module.
compiler/mercury_compile_front_end.m:
Invoke the new module if any of the three new options is set.
compiler/hlds_pred.m:
Record the item number of every predicate, function, and mode declaration
in the module being compiled. We need this for information for the
new warnings.
compiler/hlds_module.m:
Record the context of the module declaration. We use this context
for warnings about inconsistent order, since there isn't a better one.
compiler/hlds_clauses.m:
Add a mechanism to retrieve the item numbers of a set of clauses
even if they are contiguous.
Document some old data types.
compiler/error_util.m:
Add a new phase for style checks.
compiler/accumulator.m:
compiler/add_class.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pragma_tabling.m:
compiler/add_pred.m:
compiler/add_solver.m:
compiler/add_special_pred.m:
compiler/check_typeclass.m:
compiler/clause_to_proc.m:
compiler/from_ground_term_util.m:
compiler/lambda.m:
compiler/make_hlds.m:
compiler/make_hlds_passes.m:
compiler/mercury_compile.m:
compiler/par_loop_control.m:
compiler/polymorphism.m:
compiler/stm_expand.m:
compiler/table_gen.m:
compiler/unify_proc.m:
Conform the changes to the HLDS above.
compiler/typecheck_errors.m:
Fix style of error messages.
library/array2d.m:
library/assoc_list.m:
library/benchmarking.m:
library/bit_buffer.write.m:
library/bool.m:
library/builtin.m:
library/construct.m:
library/cord.m:
library/counter.m:
library/float.m:
library/injection.m:
library/lazy.m:
library/lexer.m:
library/ops.m:
library/private_builtin.m:
library/profiling_builtin.m:
library/prolog.m:
library/queue.m:
library/rational.m:
library/require.m:
library/stack.m:
library/std_util.m:
library/store.m:
library/thread.semaphore.m:
library/tree234.m:
library/univ.m:
library/version_store.m:
Move declarations or definitions around to avoid some of the warnings
that we can now generate. (There are many more left.)
Make some minor style improvements in the process.
tests/warnings/inconsistent_pred_order.{m,exp}:
tests/warnings/non_contiguous_decls.{m,exp}:
New test cases to test the new options. They are both copies of
tests/benchmarks/queens.m, with intentionally-screwed-up style.
tests/warnings/Mmakefile:
Enable the new test cases.
tests/warnings/Mercury.options:
Specify the options being tested for the new test cases.
tests/benchmarks/queens.m:
Bring the style of this module up to date (before copying it).
tests/invalid/mode_decl_in_wrong_section.err_exp:
Expect the warnings we now generate.
239 lines
7.8 KiB
Mathematica
239 lines
7.8 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2003, 2005-2007, 2011-2012 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU Library General
|
|
% Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: array2d.m.
|
|
% Author: Ralph Becket <rafe@cs.mu.oz.au>.
|
|
% Stability: medium-low.
|
|
%
|
|
% Two-dimensional rectangular (i.e. not ragged) array ADT.
|
|
%
|
|
% XXX The same caveats re: uniqueness of arrays apply to array2ds.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module array2d.
|
|
:- interface.
|
|
|
|
:- import_module array.
|
|
:- import_module list.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% A array2d is a two-dimensional array stored in row-major order
|
|
% (that is, the elements of the first row in left-to-right
|
|
% order, followed by the elements of the second row and so forth.)
|
|
%
|
|
:- type array2d(T).
|
|
|
|
:- inst array2d
|
|
---> array2d(ground, ground, array).
|
|
|
|
% XXX These are work-arounds until we get nested uniqueness working.
|
|
%
|
|
:- mode array2d_di == di(array2d).
|
|
:- mode array2d_ui == in(array2d).
|
|
:- mode array2d_uo == out(array2d).
|
|
|
|
% init(M, N, X) = array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]])
|
|
% where each XIJ = X. An exception is thrown if M < 0 or N < 0.
|
|
%
|
|
:- func init(int, int, T) = array2d(T).
|
|
:- mode init(in, in, in) = array2d_uo is det.
|
|
|
|
% array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) constructs a array2d
|
|
% of size M * N, with the special case that bounds(array2d([]), 0, 0).
|
|
%
|
|
% An exception is thrown if the sublists are not all the same length.
|
|
%
|
|
:- func array2d(list(list(T))) = array2d(T).
|
|
:- mode array2d(in) = array2d_uo is det.
|
|
|
|
% is_empty(Array):
|
|
% True iff Array contains zero elements.
|
|
%
|
|
:- pred is_empty(array2d(T)).
|
|
%:- mode is_empty(array2d_ui) is semidet.
|
|
:- mode is_empty(in) is semidet.
|
|
|
|
% A synonym for the above.
|
|
%
|
|
:- func from_lists(list(list(T))) = array2d(T).
|
|
:- mode from_lists(in) = array2d_uo is det.
|
|
|
|
% bounds(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]), M, N)
|
|
%
|
|
:- pred bounds(array2d(T), int, int).
|
|
%:- mode bounds(array2d_ui, out, out) is det.
|
|
:- mode bounds(in, out, out) is det.
|
|
|
|
% in_bounds(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]), I, J)
|
|
% succeeds iff 0 =< I < M, 0 =< J < N.
|
|
%
|
|
:- pred in_bounds(array2d(T), int, int).
|
|
%:- mode in_bounds(array2d_ui, in, in ) is semidet.
|
|
:- mode in_bounds(in, in, in ) is semidet.
|
|
|
|
% array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) ^ elem(I, J) = X
|
|
% where X is the J+1th element of the I+1th row (that is, indices
|
|
% start from zero.)
|
|
%
|
|
% An exception is thrown unless 0 =< I < M, 0 =< J < N.
|
|
%
|
|
:- func array2d(T) ^ elem(int, int) = T.
|
|
%:- mode array2d_ui ^ elem(in, in ) = out is det.
|
|
:- mode in ^ elem(in, in ) = out is det.
|
|
|
|
% T ^ unsafe_elem(I, J) is the same as T ^ elem(I, J) except that
|
|
% behaviour is undefined if not in_bounds(T, I, J).
|
|
%
|
|
:- func array2d(T) ^ unsafe_elem(int, int) = T.
|
|
%:- mode array2d_ui ^ unsafe_elem(in, in ) = out is det.
|
|
:- mode in ^ unsafe_elem(in, in ) = out is det.
|
|
|
|
% ( T0 ^ elem(I, J) := X ) = T
|
|
% where T ^ elem(II, JJ) = X if I = II, J = JJ
|
|
% and T ^ elem(II, JJ) = T0 ^ elem(II, JJ) otherwise.
|
|
%
|
|
% An exception is thrown unless 0 =< I < M, 0 =< J < N.
|
|
%
|
|
:- func ( array2d(T) ^ elem(int, int) := T ) = array2d(T).
|
|
:- mode ( array2d_di ^ elem(in, in) := in ) = array2d_uo is det.
|
|
|
|
% Pred version of the above.
|
|
%
|
|
:- pred set(int, int, T, array2d(T), array2d(T)).
|
|
:- mode set(in, in, in, array2d_di, array2d_uo) is det.
|
|
|
|
% T ^ unsafe_elem(I, J) := X is the same as T ^ elem(I, J) := X except
|
|
% that behaviour is undefined if not in_bounds(T, I, J).
|
|
%
|
|
:- func ( array2d(T) ^ unsafe_elem(int, int) := T ) = array2d(T).
|
|
:- mode ( array2d_di ^ unsafe_elem(in, in) := in ) = array2d_uo is det.
|
|
|
|
% Pred version of the above.
|
|
%
|
|
:- pred unsafe_set(int, int, T, array2d(T), array2d(T)).
|
|
:- mode unsafe_set(in, in, in, array2d_di, array2d_uo) is det.
|
|
|
|
% lists(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN])) =
|
|
% [[X11, ..., X1N], ..., [XM1, ..., XMN]]
|
|
%
|
|
:- func lists(array2d(T)) = list(list(T)).
|
|
%:- mode lists(array2d_ui) = out is det.
|
|
:- mode lists(in ) = out is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module require.
|
|
:- import_module int.
|
|
|
|
:- interface.
|
|
|
|
% This should be abstract, but needs to be exported for insts.
|
|
%
|
|
:- type array2d(T)
|
|
---> array2d(
|
|
int, % rows
|
|
int, % cols
|
|
array(T) % array
|
|
).
|
|
|
|
:- implementation.
|
|
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
init(M, N, X) =
|
|
( if M >= 0, N >= 0
|
|
then array2d(M, N, array.init(M * N, X))
|
|
else func_error("array2d.init: bounds must be non-negative")
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
array2d([]) = array2d(0, 0, make_empty_array).
|
|
array2d(Xss @ [Xs | _]) = T :-
|
|
M = length(Xss),
|
|
N = length(Xs),
|
|
A = array(condense(Xss)),
|
|
T = ( if all [Ys] ( member(Ys, Xss) => length(Ys) = N )
|
|
then array2d(M, N, A)
|
|
else func_error("array2d.array2d/1: non-rectangular list of lists")
|
|
).
|
|
|
|
is_empty(array2d(_, _, A)) :-
|
|
array.is_empty(A).
|
|
|
|
from_lists(Xss) = array2d(Xss).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
bounds(array2d(M, N, _A), M, N).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
in_bounds(array2d(M, N, _A), I, J) :-
|
|
0 =< I, I < M,
|
|
0 =< J, J < N.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
T ^ elem(I, J) =
|
|
( if in_bounds(T, I, J)
|
|
then T ^ unsafe_elem(I, J)
|
|
else func_error("array2d.elem: indices out of bounds")
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
array2d(_M, N, A) ^ unsafe_elem(I, J) = A ^ unsafe_elem(I * N + J).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
( T ^ elem(I, J) := X ) =
|
|
( if in_bounds(T, I, J)
|
|
then T ^ unsafe_elem(I, J) := X
|
|
else func_error("array2d.'elem :=': indices out of bounds")
|
|
).
|
|
|
|
set(I, J, X, A, A ^ elem(I, J) := X).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
( array2d(M, N, A) ^ unsafe_elem(I, J) := X ) =
|
|
array2d(M, N, A ^ unsafe_elem(I * N + J) := X).
|
|
|
|
unsafe_set(I, J, X, A, A ^ unsafe_elem(I, J) := X).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
lists(array2d(M, N, A)) = lists_2((M * N) - 1, N - 1, N, A, [], []).
|
|
|
|
:- func lists_2(int, int, int, array(T), list(T), list(list(T))) =
|
|
list(list(T)).
|
|
%:- mode lists_2(in, in, in, array_ui, in, in ) = out is det.
|
|
:- mode lists_2(in, in, in, in, in, in ) = out is det.
|
|
|
|
lists_2(IJ, J, N, A, Xs, Xss) =
|
|
( if 0 =< IJ then
|
|
( if 0 =< J
|
|
then lists_2(IJ - 1, J - 1, N, A, [A ^ elem(IJ) | Xs], Xss )
|
|
else lists_2(IJ, N - 1, N, A, [], [Xs | Xss])
|
|
)
|
|
else
|
|
[Xs | Xss]
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module array2d.
|
|
%---------------------------------------------------------------------------%
|