Files
mercury/compiler/mode_errors.m
Fergus Henderson 11d8161692 Add support for nested modules.
Estimated hours taken: 50

Add support for nested modules.

- module names may themselves be module-qualified
- modules may contain `:- include_module' declarations
  which name sub-modules
- a sub-module has access to all the declarations in the
  parent module (including its implementation section).

This support is not yet complete; see the BUGS and LIMITATIONS below.

LIMITATIONS
- source file names must match module names
	(just as they did previously)
- mmc doesn't allow path names on the command line any more
	(e.g. `mmc --make-int ../library/foo.m').
- import_module declarations must use the fully-qualified module name
- module qualifiers must use the fully-qualified module name
- no support for root-qualified module names
	(e.g. `:parent:child' instead of `parent:child').
- modules may not be physically nested (only logical nesting, via
  `include_module').

BUGS
- doesn't check that the parent module is imported/used before allowing
	import/use of its sub-modules.
- doesn't check that there is an include_module declaration in the
	parent for each module claiming to be a child of that parent
- privacy of private modules is not enforced

-------------------

NEWS:
	Mention that we support nested modules.

library/ops.m:
library/nc_builtin.nl:
library/sp_builtin.nl:
compiler/mercury_to_mercury.m:
	Add `include_module' as a new prefix operator.
	Change the associativity of `:' from xfy to yfx
	(since this made parsing module qualifiers slightly easier).

compiler/prog_data.m:
	Add new `include_module' declaration.
	Change the `module_name' and `module_specifier' types
	from strings to sym_names, so that module names can
	themselves be module qualified.

compiler/modules.m:
	Add predicates module_name_to_file_name/2 and
	file_name_to_module_name/2.
	Lots of changes to handle parent module dependencies,
	to create parent interface (`.int0') files, to read them in,
	to output correct dependencies information for them to the
	`.d' and `.dep' files, etc.
	Rewrite a lot of the code to improve the readability
	(add comments, use subroutines, better variable names).
	Also fix a couple of bugs:
	- generate_dependencies was using the transitive implementation
	  dependencies rather than the transitive interface dependencies
	  to compute the `.int3' dependencies when writing `.d' files
	  (this bug was introduced during crs's changes to support
	  `.trans_opt' files)
	- when creating the `.int' file, it was reading in the
	  interfaces for modules imported in the implementation section,
	  not just those in the interface section.
	  This meant that the compiler missed a lot of errors.

library/graph.m:
library/lexer.m:
library/term.m:
library/term_io.m:
library/varset.m:
compiler/*.m:
	Add `:- import_module' declarations to the interface needed
	by declarations in the interface.  (The previous version
	of the compiler did not detect these missing interface imports,
	due to the above-mentioned bug in modules.m.)

compiler/mercury_compile.m:
compiler/intermod.m:
	Change mercury_compile__maybe_grab_optfiles and
	intermod__grab_optfiles so that they grab the opt files for
	parent modules as well as the ones for imported modules.

compiler/mercury_compile.m:
	Minor changes to handle parent module dependencies.
	(Also improve the wording of the warning about trans-opt
	dependencies.)

compiler/make_hlds.m:
compiler/module_qual.m:
	Ignore `:- include_module' declarations.

compiler/module_qual.m:
	A couple of small changes to handle nested module names.

compiler/prog_out.m:
compiler/prog_util.m:
	Add new predicates string_to_sym_name/3 (prog_util.m) and
	sym_name_to_string/{2,3} (prog_out.m).

compiler/*.m:
	Replace many occurrences of `string' with `module_name'.
	Change code that prints out module names or converts
	them to strings or filenames to handle the fact that
	module names are now sym_names intead of strings.
	Also change a few places (e.g. in intermod.m, hlds_module.m)
	where the code assumed that any qualified symbol was
	fully-qualified.

compiler/prog_io.m:
compiler/prog_io_goal.m:
	Move sym_name_and_args/3, parse_qualified_term/4 and
	parse_qualified_term/5 preds from prog_io_goal.m to prog_io.m,
	since they are very similar to the parse_symbol_name/2 predicate
	already in prog_io.m.  Rewrite these predicates, both
	to improve maintainability, and to handle the newly
	allowed syntax (module-qualified module names).
	Rename parse_qualified_term/5 as `parse_implicit_qualified_term'.

compiler/prog_io.m:
	Rewrite the handling of `:- module' and `:- end_module'
	declarations, so that it can handle nested modules.
	Add code to parse `include_module' declarations.

compiler/prog_util.m:
compiler/*.m:
	Add new predicates mercury_public_builtin_module/1 and
	mercury_private_builtin_module/1 in prog_util.m.
	Change most of the hard-coded occurrences of "mercury_builtin"
	to call mercury_private_builtin_module/1 or
	mercury_public_builtin_module/1 or both.

compiler/llds_out.m:
	Add llds_out__sym_name_mangle/2, for mangling module names.

compiler/special_pred.m:
compiler/mode_util.m:
compiler/clause_to_proc.m:
compiler/prog_io_goal.m:
compiler/lambda.m:
compiler/polymorphism.m:
	Move the predicates in_mode/1, out_mode/1, and uo_mode/1
	from special_pred.m to mode_util.m, and change various
	hard-coded definitions to instead call these predicates.

compiler/polymorphism.m:
	Ensure that the type names `type_info' and `typeclass_info' are
	module-qualified in the generated code.  This avoids a problem
	where the code generated by polymorphism.m was not considered
	type-correct, due to the type `type_info' not matching
	`mercury_builtin:type_info'.

compiler/check_typeclass.m:
	Simplify the code for check_instance_pred and
	get_matching_instance_pred_ids.

compiler/mercury_compile.m:
compiler/modules.m:
	Disallow directory names in command-line arguments.

compiler/options.m:
compiler/handle_options.m:
compiler/mercury_compile.m:
compiler/modules.m:
	Add a `--make-private-interface' option.
	The private interface file `<module>.int0' contains
	all the declarations in the module; it is used for
	compiling sub-modules.

scripts/Mmake.rules:
scripts/Mmake.vars.in:
	Add support for creating `.int0' and `.date0' files
	by invoking mmc with `--make-private-interface'.

doc/user_guide.texi:
	Document `--make-private-interface' and the `.int0'
	and `.date0' file extensions.

doc/reference_manual.texi:
	Document nested modules.

util/mdemangle.c:
profiler/demangle.m:
	Demangle names with multiple module qualifiers.

tests/general/Mmakefile:
tests/general/string_format_test.m:
tests/general/string_format_test.exp:
tests/general/string__format_test.m:
tests/general/string__format_test.exp:
tests/general/.cvsignore:
	Change the `:- module string__format_test' declaration in
	`string__format_test.m' to `:- module string_format_test',
	because with the original declaration the `__' was taken
	as a module qualifier, which lead to an error message.
	Hence rename the file accordingly, to avoid the warning
	about file name not matching module name.

tests/invalid/Mmakefile:
tests/invalid/missing_interface_import.m:
tests/invalid/missing_interface_import.err_exp:
	Regression test to check that the compiler reports
	errors for missing `import_module' in the interface section.

tests/invalid/*.err_exp:
tests/warnings/unused_args_test.exp:
tests/warnings/unused_import.exp:
	Update the expected diagnostics output for the test cases to
	reflect a few minor changes to the warning messages.

tests/hard_coded/Mmakefile:
tests/hard_coded/parent.m:
tests/hard_coded/parent.child.m:
tests/hard_coded/parent.exp:
tests/hard_coded/parent2.m:
tests/hard_coded/parent2.child.m:
tests/hard_coded/parent2.exp:
	Two simple tests case for the use of nested modules with
	separate compilation.
1998-03-03 17:48:14 +00:00

1066 lines
40 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1994-1998 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.
%-----------------------------------------------------------------------------%
% File: mode_errors.m.
% Main author: fjh.
% This module contains all the error-reporting routines for the
% mode-checker.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- module mode_errors.
:- interface.
:- import_module hlds_data, hlds_pred, hlds_module, hlds_goal.
:- import_module prog_data, mode_info, (inst).
:- import_module bool, set, assoc_list, term, list.
%-----------------------------------------------------------------------------%
:- type merge_context
---> disj
; if_then_else.
:- type merge_errors == assoc_list(var, list(inst)).
:- type delayed_goal
---> delayed_goal(
set(var), % The vars it's waiting on
mode_error_info,% The reason it can't be scheduled
hlds_goal % The goal itself
).
:- type mode_error
---> mode_error_disj(merge_context, merge_errors)
% different arms of a disjunction result in
% different insts for some non-local variables
; mode_error_higher_order_pred_var(pred_or_func, var, inst, arity)
% the predicate variable in a higher-order predicate
% or function call didn't have a higher-order
% predicate or function inst of the appropriate arity
; mode_error_var_is_live(var)
% call to a predicate which will clobber its argument,
% but the argument is still live
; mode_error_var_has_inst(var, inst, inst)
% call to a predicate with an insufficiently
% instantiated variable (for preds with one mode)
; mode_error_unify_pred(var, mode_error_unify_rhs, type,
pred_or_func)
% an attempt was made to unify two higher-order
% predicate or function variables.
; mode_error_implied_mode(var, inst, inst)
% a call to a predicate with an overly
% instantiated variable would use an implied
% mode of the predicate. XXX This is temporary -
% once we've implemented implied modes we can
% get rid of it.
; mode_error_no_mode_decl
% a call to a predicate for which there are
% no mode declarations
; mode_error_no_matching_mode(list(var), list(inst))
% call to a predicate with an insufficiently
% instantiated variable (for preds with >1 mode)
; mode_error_bind_var(var_lock_reason, var, inst, inst)
% attempt to bind a non-local variable inside
% a negated context
; mode_error_non_local_lambda_var(var, inst)
% attempt to pass a live non-ground var as a
% non-local variable to a lambda goal
; mode_error_unify_var_var(var, var, inst, inst)
% attempt to unify two free variables
; mode_error_unify_var_functor(var, cons_id, list(var),
inst, list(inst))
% attempt to unify a free var with a functor containing
% free arguments
; mode_error_unify_var_lambda(var, inst, inst)
% some sort of error in
% attempt to unify a variable with lambda expression
; mode_error_conj(list(delayed_goal), schedule_culprit)
% a conjunction contains one or more unscheduleable
% goals; schedule_culprit gives the reason why
% they couldn't be scheduled.
; mode_error_final_inst(int, var, inst, inst, final_inst_error).
% one of the head variables did not have the
% expected final inst on exit from the proc
:- type schedule_culprit
---> goal_itself_was_impure
; goals_followed_by_impure_goal(hlds_goal)
; conj_floundered. % we've reached the end of a conjunction
% and there were still delayed goals
:- type final_inst_error
---> too_instantiated
; not_instantiated_enough
; wrongly_instantiated. % a catchall for anything that doesn't
% fit into the above two categories.
:- type mode_error_unify_rhs
---> error_at_var(var)
; error_at_functor(cons_id, list(var))
; error_at_lambda(list(var), list(mode)).
:- type mode_error_info
---> mode_error_info(
set(var), % the variables which caused the error
% (we will attempt to reschedule the goal
% if the one of these variables becomes
% more instantiated)
mode_error, % the nature of the error
term__context, % where the error occurred
mode_context % where the error occurred
).
%-----------------------------------------------------------------------------%
% If there were any errors recorded in the mode_info,
% report them to the user now.
%
:- pred report_mode_errors(mode_info, mode_info).
:- mode report_mode_errors(mode_info_di, mode_info_uo) is det.
% print an error message describing a mode error
:- pred report_mode_error(mode_error, mode_info, io__state, io__state).
:- mode report_mode_error(in, mode_info_no_io, di, uo) is det.
% report an error for a predicate with no mode declarations
% unless mode inference is enabled and the predicate is local.
:- pred maybe_report_error_no_modes(pred_id, pred_info, module_info,
io__state, io__state).
:- mode maybe_report_error_no_modes(in, in, in, di, uo) is det.
% initialize the mode_context.
:- pred mode_context_init(mode_context).
:- mode mode_context_init(out) is det.
% Write out the inferred `mode' declarations for a list of pred_ids.
% The bool indicates whether or not to write out determinism
% annotations on the modes (it should only be set to `yes' _after_
% determinism analysis).
:- pred write_mode_inference_messages(list(pred_id), bool, module_info,
io__state, io__state).
:- mode write_mode_inference_messages(in, 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.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module hlds_out.
:- import_module mode_info, mode_util, prog_out, mercury_to_mercury.
:- import_module options, globals.
:- import_module int, map, io, term_io, varset.
:- import_module std_util, require.
% just dispatch on the diffferent sorts of mode errors
report_mode_error(mode_error_disj(MergeContext, ErrorList), ModeInfo) -->
report_mode_error_disj(ModeInfo, MergeContext, ErrorList).
report_mode_error(mode_error_higher_order_pred_var(PredOrFunc, Var, Inst,
Arity), ModeInfo) -->
report_mode_error_higher_order_pred_var(ModeInfo, PredOrFunc, Var,
Inst, Arity).
report_mode_error(mode_error_var_is_live(Var), ModeInfo) -->
report_mode_error_var_is_live(ModeInfo, Var).
report_mode_error(mode_error_var_has_inst(Var, InstA, InstB), ModeInfo) -->
report_mode_error_var_has_inst(ModeInfo, Var, InstA, InstB).
report_mode_error(mode_error_unify_pred(Var, RHS, Type, PredOrFunc),
ModeInfo) -->
report_mode_error_unify_pred(ModeInfo, Var, RHS, Type, PredOrFunc).
report_mode_error(mode_error_implied_mode(Var, InstA, InstB), ModeInfo) -->
report_mode_error_implied_mode(ModeInfo, Var, InstA, InstB).
report_mode_error(mode_error_no_mode_decl, ModeInfo) -->
report_mode_error_no_mode_decl(ModeInfo).
report_mode_error(mode_error_bind_var(Reason, Var, InstA, InstB), ModeInfo) -->
report_mode_error_bind_var(ModeInfo, Reason, Var, InstA, InstB).
report_mode_error(mode_error_non_local_lambda_var(Var, Inst), ModeInfo) -->
report_mode_error_non_local_lambda_var(ModeInfo, Var, Inst).
report_mode_error(mode_error_unify_var_var(VarA, VarB, InstA, InstB),
ModeInfo) -->
report_mode_error_unify_var_var(ModeInfo, VarA, VarB, InstA, InstB).
report_mode_error(mode_error_unify_var_lambda(VarA, InstA, InstB),
ModeInfo) -->
report_mode_error_unify_var_lambda(ModeInfo, VarA, InstA, InstB).
report_mode_error(mode_error_unify_var_functor(Var, Name, Args, Inst,
ArgInsts), ModeInfo) -->
report_mode_error_unify_var_functor(ModeInfo, Var, Name, Args, Inst,
ArgInsts).
report_mode_error(mode_error_conj(Errors, Culprit), ModeInfo) -->
report_mode_error_conj(ModeInfo, Errors, Culprit).
report_mode_error(mode_error_no_matching_mode(Vars, Insts), ModeInfo) -->
report_mode_error_no_matching_mode(ModeInfo, Vars, Insts).
report_mode_error(mode_error_final_inst(ArgNum, Var, VarInst, Inst, Reason),
ModeInfo) -->
report_mode_error_final_inst(ModeInfo, ArgNum, Var, VarInst, Inst,
Reason).
%-----------------------------------------------------------------------------%
:- pred report_mode_error_conj(mode_info, list(delayed_goal), schedule_culprit,
io__state, io__state).
:- mode report_mode_error_conj(mode_info_no_io, in, in, di, uo) is det.
report_mode_error_conj(ModeInfo, Errors, Culprit) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ find_important_errors(Errors, ImportantErrors, OtherErrors) },
% if there's more than one error, and we have verbose-errors
% enabled, report them all
globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
( { VerboseErrors = yes, Errors = [_, _ | _] } ->
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error in conjunction. The next "),
{ list__length(Errors, NumErrors) },
io__write_int(NumErrors),
io__write_string(" error messages\n"),
prog_out__write_context(Context),
io__write_string(" indicate possible causes of this error.\n"),
report_mode_error_conj_2(ImportantErrors, VarSet, Context,
ModeInfo),
report_mode_error_conj_2(OtherErrors, VarSet, Context, ModeInfo)
;
% in the normal case, only report the first error
{ ImportantErrors = [FirstImportantError | _] }
->
report_mode_error_conj_2([FirstImportantError], VarSet, Context,
ModeInfo)
;
{ OtherErrors = [FirstOtherError | _] }
->
report_mode_error_conj_2([FirstOtherError], VarSet, Context,
ModeInfo)
;
% There wasn't any error to report! This can't happen.
{ error("report_mode_error_conj") }
),
% if the goal(s) couldn't be scheduled because we couldn't
% reorder things past an impure goal, then report that.
( { Culprit = conj_floundered },
{ true } % we've already reported everything we can
; { Culprit = goal_itself_was_impure },
prog_out__write_context(Context),
io__write_string(
" The goal could not be reordered, because it was impure.\n")
; { Culprit = goals_followed_by_impure_goal(ImpureGoal) },
prog_out__write_context(Context),
io__write_string(
" The goal could not be reordered, because\n"),
prog_out__write_context(Context),
io__write_string(
" it was followed by an impure goal.\n"),
{ ImpureGoal = _ - ImpureGoalInfo },
{ goal_info_get_context(ImpureGoalInfo, ImpureGoalContext) },
prog_out__write_context(ImpureGoalContext),
io__write_string(
" This is the location of the impure goal.\n")
).
:- pred find_important_errors(list(delayed_goal), list(delayed_goal),
list(delayed_goal)).
:- mode find_important_errors(in, out, out) is det.
find_important_errors([], [], []).
find_important_errors([Error | Errors], ImportantErrors, OtherErrors) :-
Error = delayed_goal(_, mode_error_info(_, ModeError, _, ModeContext),
_),
(
% an error is important unless it is a non-explicit unification,
% i.e. a head unification or a call argument unification
ModeContext = unify(unify_context(UnifyContext, _), _),
UnifyContext \= explicit,
% except that errors in lambda goals are important even
% if the unification that creates the lambda goal is
% an implicit one
ModeError \= mode_error_non_local_lambda_var(_, _)
->
ImportantErrors1 = ImportantErrors,
OtherErrors = [Error | OtherErrors1]
;
ImportantErrors = [Error | ImportantErrors1],
OtherErrors1 = OtherErrors
),
find_important_errors(Errors, ImportantErrors1, OtherErrors1).
:- pred report_mode_error_conj_2(list(delayed_goal), varset, term__context,
mode_info, io__state, io__state).
:- mode report_mode_error_conj_2(in, in, in, mode_info_no_io, di, uo) is det.
report_mode_error_conj_2([], _, _, _) --> [].
report_mode_error_conj_2([delayed_goal(Vars, Error, Goal) | Rest],
VarSet, Context, ModeInfo) -->
globals__io_lookup_bool_option(debug_modes, Debug),
( { Debug = yes } ->
prog_out__write_context(Context),
io__write_string("Floundered goal, waiting on { "),
{ set__to_sorted_list(Vars, VarList) },
mercury_output_vars(VarList, VarSet, no),
io__write_string(" } :\n")
;
[]
),
globals__io_lookup_bool_option(very_verbose, VeryVerbose),
( { VeryVerbose = yes } ->
io__write_string("\t\t"),
{ mode_info_get_module_info(ModeInfo, ModuleInfo) },
hlds_out__write_goal(Goal, ModuleInfo, VarSet, no, 2, ".")
;
[]
),
{ Error = mode_error_info(_, ModeError, ErrorContext, ModeContext) },
{ mode_info_set_context(ErrorContext, ModeInfo, ModeInfo1) },
{ mode_info_set_mode_context(ModeContext, ModeInfo1, ModeInfo2) },
report_mode_error(ModeError, ModeInfo2),
report_mode_error_conj_2(Rest, VarSet, Context, ModeInfo2).
%-----------------------------------------------------------------------------%
:- pred report_mode_error_disj(mode_info, merge_context, merge_errors,
io__state, io__state).
:- mode report_mode_error_disj(mode_info_no_io, in, in, di, uo) is det.
report_mode_error_disj(ModeInfo, MergeContext, ErrorList) -->
{ mode_info_get_context(ModeInfo, Context) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode mismatch in "),
write_merge_context(MergeContext),
io__write_string(".\n"),
write_merge_error_list(ErrorList, ModeInfo).
:- pred write_merge_error_list(merge_errors, mode_info, io__state, io__state).
:- mode write_merge_error_list(in, mode_info_no_io, di, uo) is det.
write_merge_error_list([], _) --> [].
write_merge_error_list([Var - Insts | Errors], ModeInfo) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
prog_out__write_context(Context),
io__write_string(" `"),
mercury_output_var(Var, VarSet, no),
io__write_string("' :: "),
output_inst_list(Insts, InstVarSet),
io__write_string(".\n"),
write_merge_error_list(Errors, ModeInfo).
:- pred write_merge_context(merge_context, io__state, io__state).
:- mode write_merge_context(in, di, uo) is det.
write_merge_context(disj) -->
io__write_string("disjunction").
write_merge_context(if_then_else) -->
io__write_string("if-then-else").
%-----------------------------------------------------------------------------%
:- pred report_mode_error_bind_var(mode_info, var_lock_reason, var, inst, inst,
io__state, io__state).
:- mode report_mode_error_bind_var(mode_info_ui, in, in, in, in, di, uo) is det.
report_mode_error_bind_var(ModeInfo, Reason, Var, VarInst, Inst) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" scope error: "),
( { Reason = negation },
io__write_string("attempt to bind a variable inside a negation.\n")
; { Reason = if_then_else },
io__write_string("attempt to bind a non-local variable\n"),
prog_out__write_context(Context),
io__write_string(" inside the condition of an if-then-else.\n")
; { Reason = lambda(PredOrFunc) },
{ hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncS) },
io__write_string("attempt to bind a non-local variable inside\n"),
prog_out__write_context(Context),
io__write_strings([" a ", PredOrFuncS, " lambda goal.\n"])
),
prog_out__write_context(Context),
io__write_string(" Variable `"),
mercury_output_var(Var, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(VarInst, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" expected instantiatedness was `"),
output_inst(Inst, InstVarSet),
io__write_string("'.\n"),
globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
( { VerboseErrors = yes } ->
( { Reason = negation },
io__write_string("\tA negation is only allowed to bind variables which are local to the\n"),
io__write_string("\tnegation, i.e. those which are implicitly existentially quantified\n"),
io__write_string("\tinside the scope of the negation.\n")
; { Reason = if_then_else },
io__write_string("\tThe condition of an if-then-else is only allowed\n"),
io__write_string("\tto bind variables which are local to the condition\n"),
io__write_string("\tor which occur only in the condition and the `then' part.\n")
; { Reason = lambda(_) },
io__write_string("\tA lambda goal is only allowed to bind its arguments\n"),
io__write_string("\tand variables local to the lambda expression.\n")
)
;
[]
).
%-----------------------------------------------------------------------------%
:- pred report_mode_error_non_local_lambda_var(mode_info, var, inst,
io__state, io__state).
:- mode report_mode_error_non_local_lambda_var(mode_info_ui, in, in,
di, uo) is det.
report_mode_error_non_local_lambda_var(ModeInfo, Var, VarInst) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error: variable `"),
mercury_output_var(Var, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(VarInst, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" expected instantiatedness for non-local variables\n"),
prog_out__write_context(Context),
io__write_string(" of lambda goals is `ground'.\n").
%-----------------------------------------------------------------------------%
:- pred report_mode_error_no_matching_mode(mode_info, list(var), list(inst),
io__state, io__state).
:- mode report_mode_error_no_matching_mode(mode_info_ui, in, in, di, uo) is det.
report_mode_error_no_matching_mode(ModeInfo, Vars, Insts) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
{ mode_info_get_module_info(ModeInfo, ModuleInfo) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error: arguments `"),
mercury_output_vars(Vars, VarSet, no),
io__write_string("'\n"),
prog_out__write_context(Context),
io__write_string(" have insts `"),
output_inst_list(Insts, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" which does not match any of the modes for "),
{ mode_info_get_mode_context(ModeInfo, ModeContext) },
( { ModeContext = call(PredId, _) } ->
hlds_out__write_pred_id(ModuleInfo, PredId)
;
{ error("report_mode_error_no_matching_mode: invalid context") }
),
io__write_string(".\n").
:- pred report_mode_error_higher_order_pred_var(mode_info, pred_or_func, var,
inst, arity,
io__state, io__state).
:- mode report_mode_error_higher_order_pred_var(mode_info_ui, in, in, in, in,
di, uo) is det.
report_mode_error_higher_order_pred_var(ModeInfo, PredOrFunc, Var, VarInst,
Arity) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error: variable `"),
mercury_output_var(Var, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(VarInst, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
( { PredOrFunc = predicate },
io__write_string(" expecting higher-order pred inst (of arity "),
io__write_int(Arity)
; { PredOrFunc = function },
io__write_string(" expecting higher-order func inst (of arity "),
{ Arity1 is Arity - 1 },
io__write_int(Arity1)
),
io__write_string(").\n").
:- pred report_mode_error_var_is_live(mode_info, var, io__state, io__state).
:- mode report_mode_error_var_is_live(mode_info_ui, in, di, uo) is det.
report_mode_error_var_is_live(ModeInfo, Var) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" unique-mode error: the called procedure would clobber\n"),
prog_out__write_context(Context),
io__write_string(" its argument, but variable `"),
mercury_output_var(Var, VarSet, no),
io__write_string("' is still live.\n").
:- pred report_mode_error_var_has_inst(mode_info, var, inst, inst,
io__state, io__state).
:- mode report_mode_error_var_has_inst(mode_info_ui, in, in, in, di, uo) is det.
report_mode_error_var_has_inst(ModeInfo, Var, VarInst, Inst) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error: variable `"),
mercury_output_var(Var, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(VarInst, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" expected instantiatedness was `"),
output_inst(Inst, InstVarSet),
io__write_string("'.\n").
:- pred report_mode_error_implied_mode(mode_info, var, inst, inst,
io__state, io__state).
:- mode report_mode_error_implied_mode(mode_info_ui, in, in, in, di, uo) is det.
report_mode_error_implied_mode(ModeInfo, Var, VarInst, Inst) -->
% This "error" message is really a "sorry, not implemented"
% message. We only print the message if we are actually
% going to generating code.
globals__io_lookup_bool_option(errorcheck_only, ErrorcheckOnly),
( { ErrorcheckOnly = no } ->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" sorry, implied modes not implemented.\n"),
prog_out__write_context(Context),
io__write_string(" Variable `"),
mercury_output_var(Var, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(VarInst, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" expected instantiatedness was `"),
output_inst(Inst, InstVarSet),
io__write_string("'.\n")
;
[]
).
:- pred report_mode_error_no_mode_decl(mode_info, io__state, io__state).
:- mode report_mode_error_no_mode_decl(mode_info_ui, di, uo) is det.
report_mode_error_no_mode_decl(ModeInfo) -->
{ mode_info_get_context(ModeInfo, Context) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" no mode declaration for called predicate.\n").
:- pred report_mode_error_unify_pred(mode_info, var, mode_error_unify_rhs,
type, pred_or_func,
io__state, io__state).
:- mode report_mode_error_unify_pred(mode_info_ui, in, in, in, in,
di, uo) is det.
report_mode_error_unify_pred(ModeInfo, X, RHS, Type, PredOrFunc) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" In unification of `"),
mercury_output_var(X, VarSet, no),
io__write_string("' with `"),
(
{ RHS = error_at_var(Y) },
mercury_output_var(Y, VarSet, no)
;
{ RHS = error_at_functor(ConsId, ArgVars) },
hlds_out__write_functor_cons_id(ConsId, ArgVars, VarSet, no)
;
{ RHS = error_at_lambda(ArgVars, ArgModes) },
io__write_string("lambda(["),
hlds_out__write_var_modes(ArgVars, ArgModes, VarSet, no),
io__write_string("] ... )")
),
io__write_string("':\n"),
prog_out__write_context(Context),
io__write_string(" mode error: attempt at higher-order unification.\n"),
prog_out__write_context(Context),
io__write_string(" Cannot unify two terms of type `"),
{ varset__init(TypeVarSet) },
mercury_output_term(Type, TypeVarSet, no),
io__write_string("'.\n"),
globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
( { VerboseErrors = yes } ->
io__write_string("\tYour code is trying to test whether two "),
hlds_out__write_pred_or_func(PredOrFunc),
io__write_string("s are equal,\n"),
io__write_string("\tby unifying them. In the general case, testing equivalence\n"),
io__write_string("\tof "),
hlds_out__write_pred_or_func(PredOrFunc),
io__write_string("s is an undecidable problem,\n"),
io__write_string("\tand so this is not allowed by the Mercury mode system.\n"),
io__write_string("\tIn some cases, you can achieve the same effect by\n"),
io__write_string("\twriting an explicit universal quantification,\n"),
io__write_string("\te.g. `all [X] call(P, X) <=> call(Q, X)',"),
io__write_string(" instead of `P = Q'.\n")
;
[]
).
%-----------------------------------------------------------------------------%
:- pred report_mode_error_unify_var_var(mode_info, var, var, inst, inst,
io__state, io__state).
:- mode report_mode_error_unify_var_var(mode_info_ui, in, in, in, in, di, uo)
is det.
report_mode_error_unify_var_var(ModeInfo, X, Y, InstX, InstY) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error in unification of `"),
mercury_output_var(X, VarSet, no),
io__write_string("' and `"),
mercury_output_var(Y, VarSet, no),
io__write_string("'.\n"),
prog_out__write_context(Context),
io__write_string(" Variable `"),
mercury_output_var(X, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(InstX, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" variable `"),
mercury_output_var(Y, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(InstY, InstVarSet),
io__write_string("'.\n").
%-----------------------------------------------------------------------------%
:- pred report_mode_error_unify_var_lambda(mode_info, var, inst, inst,
io__state, io__state).
:- mode report_mode_error_unify_var_lambda(mode_info_ui, in, in, in, di, uo)
is det.
report_mode_error_unify_var_lambda(ModeInfo, X, InstX, InstY) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error in unification of `"),
mercury_output_var(X, VarSet, no),
io__write_string("' and lambda expression.\n"),
prog_out__write_context(Context),
io__write_string(" Variable `"),
mercury_output_var(X, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(InstX, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" lambda expression has instantiatedness `"),
output_inst(InstY, InstVarSet),
io__write_string("'.\n").
%-----------------------------------------------------------------------------%
:- pred report_mode_error_unify_var_functor(mode_info, var, cons_id, list(var),
inst, list(inst), io__state, io__state).
:- mode report_mode_error_unify_var_functor(mode_info_ui, in, in, in, in, in,
di, uo) is det.
report_mode_error_unify_var_functor(ModeInfo, X, ConsId, Args, InstX, ArgInsts)
-->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error in unification of `"),
mercury_output_var(X, VarSet, no),
io__write_string("' and `"),
hlds_out__write_functor_cons_id(ConsId, Args, VarSet, no),
io__write_string("'.\n"),
prog_out__write_context(Context),
io__write_string(" Variable `"),
mercury_output_var(X, VarSet, no),
io__write_string("' has instantiatedness `"),
output_inst(InstX, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" term `"),
hlds_out__write_functor_cons_id(ConsId, Args, VarSet, no),
( { Args \= [] } ->
io__write_string("'\n"),
prog_out__write_context(Context),
io__write_string(" has instantiatedness `"),
mercury_output_cons_id(ConsId, no),
io__write_string("("),
output_inst_list(ArgInsts, InstVarSet),
io__write_string(")")
;
io__write_string("' has instantiatedness `"),
mercury_output_cons_id(ConsId, no)
),
io__write_string("'.\n").
%-----------------------------------------------------------------------------%
:- pred mode_info_write_context(mode_info, io__state, io__state).
:- mode mode_info_write_context(mode_info_no_io, di, uo) is det.
mode_info_write_context(ModeInfo) -->
{ mode_info_get_module_info(ModeInfo, ModuleInfo) },
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_predid(ModeInfo, PredId) },
{ mode_info_get_procid(ModeInfo, ProcId) },
{ module_info_preds(ModuleInfo, Preds) },
{ map__lookup(Preds, PredId, PredInfo) },
{ pred_info_procedures(PredInfo, Procs) },
{ pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
{ map__lookup(Procs, ProcId, ProcInfo) },
{ proc_info_declared_argmodes(ProcInfo, Modes0) },
{ strip_builtin_qualifiers_from_mode_list(Modes0, Modes) },
{ pred_info_name(PredInfo, Name0) },
{ Name = unqualified(Name0) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
{ MaybeDet = no },
prog_out__write_context(Context),
io__write_string("In clause for `"),
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).
%-----------------------------------------------------------------------------%
:- pred report_mode_error_final_inst(mode_info, int, var, inst, inst,
final_inst_error, io__state, io__state).
:- mode report_mode_error_final_inst(mode_info_ui, in, in, in, in, in,
di, uo) is det.
report_mode_error_final_inst(ModeInfo, ArgNum, Var, VarInst, Inst, Reason) -->
{ mode_info_get_context(ModeInfo, Context) },
{ mode_info_get_varset(ModeInfo, VarSet) },
{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
mode_info_write_context(ModeInfo),
prog_out__write_context(Context),
io__write_string(" mode error: argument "),
io__write_int(ArgNum),
( { Reason = too_instantiated } ->
io__write_string(" became too instantiated")
; { Reason = not_instantiated_enough } ->
io__write_string(" did not get sufficiently instantiated")
;
% I don't think this can happen. But just in case...
io__write_string(" had the wrong instantiatedness")
),
io__write_string(".\n"),
prog_out__write_context(Context),
io__write_string(" Final instantiatedness of `"),
mercury_output_var(Var, VarSet, no),
io__write_string("' was `"),
output_inst(VarInst, InstVarSet),
io__write_string("',\n"),
prog_out__write_context(Context),
io__write_string(" expected final instantiatedness was `"),
output_inst(Inst, InstVarSet),
io__write_string("'.\n").
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
mode_context_init(uninitialized).
%-----------------------------------------------------------------------------%
% XXX some parts of the mode context never get set up
:- pred write_mode_context(mode_context, term__context, module_info,
io__state, io__state).
:- mode write_mode_context(in, in, in, di, uo) is det.
write_mode_context(uninitialized, _Context, _ModuleInfo) -->
[].
write_mode_context(higher_order_call(PredOrFunc, ArgNum), Context, _ModuleInfo)
-->
prog_out__write_context(Context),
io__write_string(" in "),
( { ArgNum = 0 } ->
io__write_string("higher-order "),
hlds_out__write_pred_or_func(PredOrFunc),
io__write_string(" call:\n")
;
io__write_string("argument "),
io__write_int(ArgNum),
io__write_string(" of higher-order "),
hlds_out__write_pred_or_func(PredOrFunc),
io__write_string(" call\n"),
prog_out__write_context(Context),
io__write_string(" (i.e. in "),
( { ArgNum = 1 } ->
io__write_string("the "),
hlds_out__write_pred_or_func(PredOrFunc),
io__write_string(" term")
;
io__write_string("argument "),
{ ArgNum1 is ArgNum - 1 },
io__write_int(ArgNum1),
io__write_string(" of the called "),
hlds_out__write_pred_or_func(PredOrFunc)
),
io__write_string("):\n")
).
write_mode_context(call(PredId, ArgNum), Context, ModuleInfo) -->
prog_out__write_context(Context),
io__write_string(" in "),
( { ArgNum = 0 } ->
[]
;
io__write_string("argument "),
io__write_int(ArgNum),
io__write_string(" of ")
),
io__write_string("call to "),
hlds_out__write_pred_id(ModuleInfo, PredId),
io__write_string(":\n").
write_mode_context(unify(UnifyContext, _Side), Context, _ModuleInfo) -->
hlds_out__write_unify_context(UnifyContext, Context).
%-----------------------------------------------------------------------------%
maybe_report_error_no_modes(PredId, PredInfo, ModuleInfo) -->
{ pred_info_import_status(PredInfo, ImportStatus) },
( { ImportStatus = local } ->
globals__io_lookup_bool_option(infer_modes, InferModesOpt),
( { InferModesOpt = yes } ->
[]
;
io__set_exit_status(1),
{ pred_info_context(PredInfo, Context) },
prog_out__write_context(Context),
io__write_string("Error: no mode declaration for "),
hlds_out__write_pred_id(ModuleInfo, PredId),
io__write_string(".\n"),
globals__io_lookup_bool_option(verbose_errors,
VerboseErrors),
( { VerboseErrors = yes } ->
prog_out__write_context(Context),
io__write_string(
" (Use `--infer-modes' to enable mode inference.)\n")
;
[]
)
)
;
io__set_exit_status(1),
{ pred_info_context(PredInfo, Context) },
prog_out__write_context(Context),
io__write_string("Error: no mode declaration for exported\n"),
prog_out__write_context(Context),
io__write_string(" "),
hlds_out__write_pred_id(ModuleInfo, PredId),
io__write_string(".\n")
).
%-----------------------------------------------------------------------------%
% write out the inferred `mode' declarations for a list of pred_ids.
write_mode_inference_messages([], _, _) --> [].
write_mode_inference_messages([PredId | PredIds], OutputDetism, ModuleInfo) -->
{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
{ pred_info_get_markers(PredInfo, Markers) },
( { check_marker(Markers, infer_modes) } ->
{ pred_info_procedures(PredInfo, Procs) },
{ map__keys(Procs, ProcIds) },
write_mode_inference_messages_2(ProcIds, Procs, PredInfo,
OutputDetism)
;
[]
),
write_mode_inference_messages(PredIds, OutputDetism, ModuleInfo).
% write out the inferred `mode' declarations for a list of
% proc_ids
:- pred write_mode_inference_messages_2(list(proc_id), proc_table, pred_info,
bool, io__state, io__state).
:- mode write_mode_inference_messages_2(in, in, in, in, di, uo) is det.
write_mode_inference_messages_2([], _, _, _) --> [].
write_mode_inference_messages_2([ProcId | ProcIds], Procs, PredInfo,
OutputDetism) -->
{ map__lookup(Procs, ProcId, ProcInfo) },
write_mode_inference_message(PredInfo, ProcInfo, OutputDetism),
write_mode_inference_messages_2(ProcIds, Procs, PredInfo, OutputDetism).
% write out the inferred `mode' declaration
% for a single function or predicate.
:- pred write_mode_inference_message(pred_info, proc_info, bool,
io__state, io__state).
:- mode write_mode_inference_message(in, in, in, di, uo) is det.
write_mode_inference_message(PredInfo, ProcInfo, OutputDetism) -->
{ pred_info_name(PredInfo, PredName) },
{ Name = unqualified(PredName) },
{ pred_info_context(PredInfo, Context) },
{ proc_info_argmodes(ProcInfo, Modes0) },
{ varset__init(VarSet) },
{ pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
( { OutputDetism = yes } ->
{ proc_info_inferred_determinism(ProcInfo, Detism) },
{ MaybeDet = yes(Detism) }
;
{ MaybeDet = no }
),
prog_out__write_context(Context),
{ strip_builtin_qualifiers_from_mode_list(Modes0, Modes) },
io__write_string("Inferred "),
( { PredOrFunc = predicate },
mercury_output_pred_mode_decl(VarSet, Name, Modes,
MaybeDet, Context)
; { PredOrFunc = function },
{ pred_args_to_func_args(Modes, ArgModes, RetMode) },
mercury_output_func_mode_decl(VarSet, Name, ArgModes, RetMode,
MaybeDet, Context)
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% If there were any errors recorded in the mode_info,
% report them to the user now.
report_mode_errors(ModeInfo0, ModeInfo) :-
mode_info_get_errors(ModeInfo0, Errors),
( Errors = [FirstError | _] -> % XXX Why do we only report the first?
FirstError = mode_error_info(_, ModeError,
Context, ModeContext),
mode_info_set_context(Context, ModeInfo0, ModeInfo1),
mode_info_set_mode_context(ModeContext, ModeInfo1, ModeInfo2),
mode_info_get_io_state(ModeInfo2, IOState0),
report_mode_error(ModeError, ModeInfo2,
IOState0, IOState),
mode_info_set_io_state(ModeInfo2, IOState, ModeInfo)
;
ModeInfo = ModeInfo0
).
%-----------------------------------------------------------------------------%
:- pred output_inst((inst), varset, io__state, io__state).
:- mode output_inst(in, in, di, uo) is det.
output_inst(Inst0, VarSet) -->
{ strip_builtin_qualifiers_from_inst(Inst0, Inst) },
mercury_output_inst(Inst, VarSet).
:- pred output_inst_list(list(inst), varset, io__state, io__state).
:- mode output_inst_list(in, in, di, uo) is det.
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).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%