diff: report errors for duplicate mode declarations
Fergus Henderson
fjh at cs.mu.oz.au
Sun Nov 23 15:31:15 AEDT 1997
Report an error for duplicate mode declarations.
compiler/modes.m:
Check for duplicate mode declarations.
compiler/modecheck_call.m:
Add new predicate modes_are_indistinguishable, for use by modes.m.
compiler/mode_errors.m:
Add predicate report_indistinguishable_mode_error to mode_errors.m,
so that modes.m can use it to report duplicate mode declarations.
compiler/mode_errors.m:
compiler/mercury_to_mercury.m:
Move some code in mode_errors.m into a new predicate
mercury_output_mode_subdecls/8 in mercury_to_mercury.m.
compiler/make_hlds.m:
Update a few comments.
tests/invalid/Mmakefile:
tests/invalid/duplicate_modes.m:
tests/invalid/duplicate_modes.err_exp:
Test cases for the above change.
cvs diff -N compiler/make_hlds.m compiler/mercury_to_mercury.m compiler/mode_errors.m compiler/modecheck_call.m compiler/modes.m tests/invalid/Mmakefile tests/invalid/duplicate_modes.err_exp tests/invalid/duplicate_modes.m
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.243
diff -u -r1.243 make_hlds.m
--- make_hlds.m 1997/11/02 12:28:53 1.243
+++ make_hlds.m 1997/11/23 04:27:25
@@ -1439,12 +1439,11 @@
;
[]
),
- % add the mode declaration to the proc_info for this procedure.
- % XXX we should check that this mode declaration
- % isn't the same as an existing one
+
+ % add the mode declaration to the pred_info for this procedure.
{ ArgLives = no },
{ add_new_proc(PredInfo0, Arity, Modes, yes(Modes), ArgLives,
- MaybeDet, MContext, PredInfo, _) },
+ MaybeDet, MContext, PredInfo, _NewProcId) },
{ map__det_update(Preds0, PredId, PredInfo, Preds) },
{ predicate_table_set_preds(PredicateTable1, Preds, PredicateTable) },
{ module_info_set_predicate_table(ModuleInfo0, PredicateTable,
@@ -1514,6 +1513,7 @@
% Higher numbers mean lower priority.
% This works because mode analysis tries each mode in turn,
% starting with the lowest-numbered modes.
+ % XXX This is obsolete!
:- pred determinism_priority(determinism, int).
:- mode determinism_priority(in, out) is det.
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.119
diff -u -r1.119 mercury_to_mercury.m
--- mercury_to_mercury.m 1997/10/09 09:38:54 1.119
+++ mercury_to_mercury.m 1997/11/23 03:06:38
@@ -34,14 +34,19 @@
maybe(determinism), term__context, io__state, io__state).
:- mode mercury_output_pred_mode_decl(in, in, in, in, in, di, uo) is det.
-:- pred mercury_output_pred_mode_subdecl(varset, sym_name, list(mode),
- maybe(determinism), term__context, io__state, io__state).
-:- mode mercury_output_pred_mode_subdecl(in, in, in, in, in, di, uo) is det.
-
:- pred mercury_output_func_mode_decl(varset, sym_name, list(mode), mode,
maybe(determinism), term__context, io__state, io__state).
:- mode mercury_output_func_mode_decl(in, in, in, in, in, in, di, uo) is det.
+:- pred mercury_output_mode_subdecl(pred_or_func, varset, sym_name,
+ list(mode), maybe(determinism), term__context,
+ io__state, io__state).
+:- mode mercury_output_mode_subdecl(in, in, in, in, in, in, di, uo) is det.
+
+:- pred mercury_output_pred_mode_subdecl(varset, sym_name, list(mode),
+ maybe(determinism), term__context, io__state, io__state).
+:- mode mercury_output_pred_mode_subdecl(in, in, in, in, in, di, uo) is det.
+
:- pred mercury_output_func_mode_subdecl(varset, sym_name, list(mode), mode,
maybe(determinism), term__context, io__state, io__state).
:- mode mercury_output_func_mode_subdecl(in, in, in, in, in, in, di, uo) is det.
@@ -1151,6 +1156,19 @@
io__write_string(".\n").
%-----------------------------------------------------------------------------%
+
+ % Output a mode declaration for a predicate or function.
+
+mercury_output_mode_subdecl(PredOrFunc, InstVarSet, Name, Modes, MaybeDet,
+ Context) -->
+ ( { PredOrFunc = predicate },
+ mercury_output_pred_mode_subdecl(InstVarSet, Name, Modes,
+ MaybeDet, Context)
+ ; { PredOrFunc = function },
+ { pred_args_to_func_args(Modes, ArgModes, RetMode) },
+ mercury_output_func_mode_subdecl(InstVarSet, Name, ArgModes,
+ RetMode, MaybeDet, Context)
+ ).
% Output a mode declaration for a predicate.
Index: compiler/mode_errors.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mode_errors.m,v
retrieving revision 1.47
diff -u -r1.47 mode_errors.m
--- mode_errors.m 1997/07/27 15:01:04 1.47
+++ mode_errors.m 1997/11/23 04:16:07
@@ -141,6 +141,13 @@
io__state, io__state).
:- mode write_mode_inference_messages(in, in, di, uo) is det.
+ % report an error for the case when two mode declarations
+ % declare indistinguishable modes
+
+:- pred report_indistinguishable_modes_error(proc_id, proc_id,
+ pred_id, pred_info, module_info, io__state, io__state).
+:- mode report_indistinguishable_modes_error(in, in, in, in, in, di, uo) is det.
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -667,14 +674,8 @@
prog_out__write_context(Context),
io__write_string("In clause for `"),
- ( { PredOrFunc = predicate },
- mercury_output_pred_mode_subdecl(InstVarSet, Name, Modes,
- MaybeDet, Context)
- ; { PredOrFunc = function },
- { pred_args_to_func_args(Modes, ArgModes, RetMode) },
- mercury_output_func_mode_subdecl(InstVarSet, Name, ArgModes,
- RetMode, MaybeDet, Context)
- ),
+ mercury_output_mode_subdecl(PredOrFunc, InstVarSet, Name, Modes,
+ MaybeDet, Context),
io__write_string("':\n"),
{ mode_info_get_mode_context(ModeInfo, ModeContext) },
write_mode_context(ModeContext, Context, ModuleInfo).
@@ -910,6 +911,66 @@
output_inst_list(Insts0, VarSet) -->
{ strip_builtin_qualifiers_from_inst_list(Insts0, Insts) },
mercury_output_inst_list(Insts, VarSet).
+
+%-----------------------------------------------------------------------------%
+
+report_indistinguishable_modes_error(OldProcId, NewProcId,
+ PredId, PredInfo, ModuleInfo) -->
+
+ io__set_exit_status(1),
+
+ { pred_info_procedures(PredInfo, Procs) },
+ { map__lookup(Procs, OldProcId, OldProcInfo) },
+ { map__lookup(Procs, NewProcId, NewProcInfo) },
+ { proc_info_context(OldProcInfo, OldContext) },
+ { proc_info_context(NewProcInfo, NewContext) },
+
+ prog_out__write_context(NewContext),
+ io__write_string("In mode declarations for "),
+ hlds_out__write_pred_id(ModuleInfo, PredId),
+ io__write_string(":\n"),
+
+ prog_out__write_context(NewContext),
+ io__write_string(" error: duplicate mode declaration.\n"),
+
+ globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
+ ( { VerboseErrors = yes } ->
+ prog_out__write_context(NewContext),
+ io__write_string(" Modes `"),
+ output_mode_decl(OldProcId, PredInfo),
+ io__write_string("'\n"),
+
+ prog_out__write_context(NewContext),
+ io__write_string(" and `"),
+ output_mode_decl(NewProcId, PredInfo),
+ io__write_string("'\n"),
+
+ prog_out__write_context(NewContext),
+ io__write_string(" are indistinguishable.\n")
+ ;
+ []
+ ),
+
+ prog_out__write_context(OldContext),
+ io__write_string(
+ " Here is the conflicting mode declaration.\n").
+
+:- pred output_mode_decl(proc_id, pred_info, io__state, io__state).
+:- mode output_mode_decl(in, in, di, uo) is det.
+
+output_mode_decl(ProcId, PredInfo) -->
+ { pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
+ { pred_info_name(PredInfo, Name0) },
+ { pred_info_procedures(PredInfo, Procs) },
+ { map__lookup(Procs, ProcId, ProcInfo) },
+ { proc_info_declared_argmodes(ProcInfo, Modes0) },
+ { proc_info_declared_determinism(ProcInfo, MaybeDet) },
+ { proc_info_context(ProcInfo, Context) },
+ { varset__init(InstVarSet) },
+ { Name = unqualified(Name0) },
+ { strip_builtin_qualifiers_from_mode_list(Modes0, Modes) },
+ mercury_output_mode_subdecl(PredOrFunc, InstVarSet, Name, Modes,
+ MaybeDet, Context).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: compiler/modecheck_call.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modecheck_call.m,v
retrieving revision 1.17
diff -u -r1.17 modecheck_call.m
--- modecheck_call.m 1997/10/15 07:39:45 1.17
+++ modecheck_call.m 1997/11/23 03:14:01
@@ -45,6 +45,15 @@
:- mode modecheck_higher_order_func_call(in, in, in, in, out,
mode_info_di, mode_info_uo) is det.
+ %
+ % Given two modes of a predicate, figure out whether
+ % they are indistinguishable; that is, whether any valid call to
+ % one mode would also be a valid call to the other.
+ % (If so, it is a mode error.)
+ %
+:- pred modes_are_indistinguishable(proc_id, proc_id, pred_info, module_info).
+:- mode modes_are_indistinguishable(in, in, in, in) is semidet.
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -436,6 +445,51 @@
%-----------------------------------------------------------------------------%
+ %
+ % Given two modes of a predicate, figure out whether
+ % they are indistinguishable; that is, whether any valid call to
+ % one mode would also be a valid call to the other.
+ % (If so, it is a mode error.)
+ %
+ % The code for this is similar to the code for compare_procs/5 below.
+ %
+modes_are_indistinguishable(ProcId, OtherProcId, PredInfo, ModuleInfo) :-
+ pred_info_procedures(PredInfo, Procs),
+ map__lookup(Procs, ProcId, ProcInfo),
+ map__lookup(Procs, OtherProcId, OtherProcInfo),
+ %
+ % Compare the initial insts of the arguments
+ %
+ proc_info_argmodes(ProcInfo, ProcArgModes),
+ proc_info_argmodes(OtherProcInfo, OtherProcArgModes),
+ mode_list_get_initial_insts(ProcArgModes, ModuleInfo, InitialInsts),
+ mode_list_get_initial_insts(OtherProcArgModes, ModuleInfo,
+ OtherInitialInsts),
+ compare_inst_list(InitialInsts, OtherInitialInsts, CompareInsts,
+ ModuleInfo),
+ CompareInsts = same,
+ %
+ % Compare the expected livenesses of the arguments
+ %
+ get_arg_lives(ProcArgModes, ModuleInfo, ProcArgLives),
+ get_arg_lives(OtherProcArgModes, ModuleInfo, OtherProcArgLives),
+ compare_liveness_list(ProcArgLives, OtherProcArgLives, CompareLives),
+ CompareLives = same,
+ %
+ % Compare the determinisms --
+ % If both are cc_, or if both are not cc_,
+ % then they are indistinguishable.
+ %
+ proc_info_interface_determinism(ProcInfo, Detism),
+ proc_info_interface_determinism(OtherProcInfo, OtherDetism),
+ determinism_components(Detism, _CanFail, Solns),
+ determinism_components(OtherDetism, _OtherCanFail, OtherSolns),
+ ( Solns = at_most_many_cc, OtherSolns = at_most_many_cc
+ ; Solns \= at_most_many_cc, OtherSolns \= at_most_many_cc
+ ).
+
+%-----------------------------------------------------------------------------%
+
/*
The algorithm for choose_best_match is supposed to be equivalent
to the following specification:
@@ -497,8 +551,11 @@
%
% Given two modes of a predicate, figure out whether
- % one of the is a better match than the other,
+ % one of them is a better match than the other,
% for calls which could match either mode.
+ %
+ % The code for this is similar to the code for
+ % modes_are_indistiguisable/4 above.
%
:- pred compare_proc(proc_id, proc_id, match, proc_table, mode_info).
:- mode compare_proc(in, in, out, in, mode_info_ui) is det.
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.206
diff -u -r1.206 modes.m
--- modes.m 1997/11/13 06:27:07 1.206
+++ modes.m 1997/11/23 04:11:44
@@ -427,8 +427,11 @@
{ NumErrors = 0 },
{ Changed = Changed0 }
;
+ check_for_indistinguishable_modes(ProcIds, PredId, PredInfo0,
+ ModuleInfo0, 0, NumErrors0),
modecheck_procs(ProcIds, PredId, ModuleInfo0, Changed0, 0,
- ModuleInfo, Changed, NumErrors)
+ ModuleInfo, Changed, NumErrors1),
+ { NumErrors is NumErrors0 + NumErrors1 }
).
% Iterate over the list of modes for a predicate.
@@ -448,6 +451,52 @@
% recursively process the remaining modes
modecheck_procs(ProcIds, PredId, ModuleInfo1, Changed1,
Errs1, ModuleInfo, Changed, Errs).
+
+%-----------------------------------------------------------------------------%
+
+:- pred check_for_indistinguishable_modes(list(proc_id),
+ pred_id, pred_info, module_info, int, int,
+ io__state, io__state).
+:- mode check_for_indistinguishable_modes(in, in, in, in, in, out,
+ di, uo) is det.
+
+check_for_indistinguishable_modes([], _, _, _, NumErrors, NumErrors) --> [].
+check_for_indistinguishable_modes([ProcId | ProcIds],
+ PredId, PredInfo, ModuleInfo, NumErrors0, NumErrors) -->
+ check_for_indistinguishable_mode(ProcIds, ProcId,
+ PredId, PredInfo, ModuleInfo, NumErrors0, NumErrors1),
+ check_for_indistinguishable_modes(ProcIds,
+ PredId, PredInfo, ModuleInfo, NumErrors1, NumErrors).
+
+:- pred check_for_indistinguishable_mode(list(proc_id), proc_id,
+ pred_id, pred_info, module_info, int, int,
+ io__state, io__state).
+:- mode check_for_indistinguishable_mode(in, in, in, in, in, in, out,
+ di, uo) is det.
+
+ % For each mode in the list, check that either that mode is the
+ % new mode we just added, or that it is distinguishable from the
+ % new mode. If we find a mode that is indistinguishable from the
+ % one we just added, report an error.
+
+check_for_indistinguishable_mode([], _, _, _, _, NumErrors, NumErrors) --> [].
+check_for_indistinguishable_mode([ProcId | ProcIds], NewProcId,
+ PredId, PredInfo, ModuleInfo, NumErrors0, NumErrors) -->
+ (
+ {
+ ProcId = NewProcId
+ ;
+ \+ modes_are_indistinguishable(ProcId, NewProcId,
+ PredInfo, ModuleInfo)
+ }
+ ->
+ check_for_indistinguishable_mode(ProcIds, NewProcId,
+ PredId, PredInfo, ModuleInfo, NumErrors0, NumErrors)
+ ;
+ report_indistinguishable_modes_error(ProcId, NewProcId,
+ PredId, PredInfo, ModuleInfo),
+ { NumErrors is NumErrors0 + 1 }
+ ).
%-----------------------------------------------------------------------------%
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.4
diff -u -r1.4 Mmakefile
--- Mmakefile 1997/11/17 05:48:40 1.4
+++ Mmakefile 1997/11/23 04:21:46
@@ -12,6 +12,7 @@
circ_type.m \
constructor_warning.m \
det_errors.m \
+ duplicate_modes.m \
errors.m \
errors1.m \
errors2.m \
@@ -49,6 +50,7 @@
MCFLAGS-multisoln_func = --infer-types
MCFLAGS-any_mode = --infer-types
+MCFLAGS-duplicate_modes = --verbose-error-messages
DEPS= $(SOURCES:%.m=%.dep)
DEPENDS= $(SOURCES:%.m=%.depend)
Index: tests/invalid/duplicate_modes.err_exp
===================================================================
RCS file: duplicate_modes.err_exp
diff -N duplicate_modes.err_exp
--- /dev/null Sun Nov 23 15:00:37 1997
+++ duplicate_modes.err_exp Sun Nov 23 15:20:00 1997
@@ -0,0 +1,18 @@
+duplicate_modes.m:004: In mode declarations for predicate `duplicate_modes:p/0':
+duplicate_modes.m:004: error: duplicate mode declaration.
+duplicate_modes.m:004: Modes `p'
+duplicate_modes.m:004: and `p is det'
+duplicate_modes.m:004: are indistinguishable.
+duplicate_modes.m:003: Here is the conflicting mode declaration.
+duplicate_modes.m:008: In mode declarations for predicate `duplicate_modes:q/2':
+duplicate_modes.m:008: error: duplicate mode declaration.
+duplicate_modes.m:008: Modes `q(in, out) is det'
+duplicate_modes.m:008: and `q((ground -> ground), (free -> ground)) is det'
+duplicate_modes.m:008: are indistinguishable.
+duplicate_modes.m:009: Here is the conflicting mode declaration.
+duplicate_modes.m:015: In mode declarations for predicate `duplicate_modes:r/2':
+duplicate_modes.m:015: error: duplicate mode declaration.
+duplicate_modes.m:015: Modes `r(in, in) is det'
+duplicate_modes.m:015: and `r(in, in) is semidet'
+duplicate_modes.m:015: are indistinguishable.
+duplicate_modes.m:014: Here is the conflicting mode declaration.
Index: tests/invalid/duplicate_modes.m
===================================================================
RCS file: duplicate_modes.m
diff -N duplicate_modes.m
--- /dev/null Sun Nov 23 15:00:37 1997
+++ duplicate_modes.m Sun Nov 23 15:21:57 1997
@@ -0,0 +1,34 @@
+:- module duplicate_modes.
+
+:- pred p.
+:- mode p is det.
+p.
+
+:- pred q(int, int).
+:- mode q(ground -> ground, free -> ground) is det.
+:- mode q(in, out) is det.
+
+q(X, X).
+
+:- pred r(int, int).
+:- mode r(in, in) is det.
+:- mode r(in, in) is semidet.
+
+r(_, _).
+
+% this one is legal (albeit not yet supported)
+:- pred s(int, int).
+:- mode s(in, out) is multi.
+:- mode s(in, out) is cc_multi.
+
+s(_, 42).
+s(_, 43).
+
+% this one is legal (albeit not yet supported)
+:- pred t(int, int).
+:- mode t(in(bound(1)), out) is multi.
+:- mode t(in(bound(2)), out) is cc_multi.
+
+t(_, 42).
+t(_, 43).
+
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list