Files
mercury/compiler/undef_modes.m
Fergus Henderson f7e5d837e1 A bunch of bug fixes!
code_info.m:
	Bug fix: change generate_pre_commit and generate_commit so that
	the values which need to be saved and restored are always pushed
	onto the det stack, even in nondet predicates.  The reason is
	that if the committed goal fails, curfr is not valid, so we
	can't restore the fields from the nondet stack.
	(This way may well be more efficient anyway.)

disj_gen.m, ite_gen.m:
	Handle the case when the current failure continuation is unknown
	on entry to the disjunction or nondet if-then-else by creating
	a new frame on the nondet stack.  (Originally we just aborted
	in this case; recently we "fixed" this, but it turned out that
	the fix was not correct, for the same reason as the above-mentioned
	bug in pre_commit/commit.

llds.m:
	Add succfr/1 and prevfr/1 to the rval type in llds.m,
	since they were needed by the above bug fixes.
	(This caused dozens of changes elsewhere to handle the
	new types.)
	Also fix a trivial bug that I recently introduced which
	prevented --mod-comments from working.

live_vars.m:
	Fix bug in allocation of stack slots for nondet code.
	(This is the one that caused the bug that ksiew and I found
	when writing a calculator program.)

peephole.m:
	Disable the succeed_discard() optimization, since it
	causes incorrect code to be generated.  It was replacing
	modframe(do_fail) ... succeed() with
	modframe(do_fail) ... succeed_discard() even when there were
	instructions such as mkframe() in between.

modes.m, hlds.m:
	When modechecking switches, record the binding of the switch variable
	as we enter each case, so that we get the determinism analysis
	right.

mercury_compile.pp:
	Make sure that we set the exit status to be non-zero if we
	find any errors.

typecheck.m, modes.m, undef_types.m, undef_modes.m:
	Don't invoke type-checking if there are undefined types.
	Don't invoke mode-checking if there are undefined modes.
	This avoids the problem of the compiler aborting with an
	internal error if there are undefined types/modes.
1995-05-12 13:44:58 +00:00

321 lines
12 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1995 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.
%-----------------------------------------------------------------------------%
:- module undef_modes.
% Detects undefined `inst's and `mode's and reports appropriate error
% messages.
% Main author: fjh.
%-----------------------------------------------------------------------------%
:- interface.
:- import_module hlds, io, std_util.
:- pred check_undefined_modes(module_info, module_info, bool,
io__state, io__state).
:- mode check_undefined_modes(in, out, out, di, uo) is det.
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module prog_io, prog_out, hlds_out, list, map, std_util, require.
% Check for any possible undefined insts/modes.
% Should we add a definition for undefined insts/modes?
check_undefined_modes(Module, Module, FoundError) -->
io__get_exit_status(ExitStatus0),
io__set_exit_status(0),
{ module_info_insts(Module, InstDefns) },
{ inst_table_get_user_insts(InstDefns, UserInstDefns) },
{ map__keys(UserInstDefns, InstIds) },
find_undef_inst_bodies(InstIds, UserInstDefns),
{ module_info_modes(Module, ModeDefns) },
{ map__keys(ModeDefns, ModeIds) },
find_undef_mode_bodies(ModeIds, ModeDefns, UserInstDefns),
{ module_info_preds(Module, Preds) },
{ module_info_predids(Module, PredIds) },
find_undef_pred_modes(PredIds, Preds, ModeDefns, UserInstDefns),
io__get_exit_status(ExitStatus1),
( { ExitStatus1 = 0 } ->
{ FoundError = no }
;
{ FoundError = yes }
),
io__set_exit_status(ExitStatus0).
% Find any undefined insts/modes used in predicate mode declarations.
:- pred find_undef_pred_modes(list(pred_id), pred_table, mode_table,
user_inst_table, io__state, io__state).
:- mode find_undef_pred_modes(in, in, in, in, di, uo) is det.
find_undef_pred_modes([], _Preds, _ModeDefns, _InstDefns) --> [].
find_undef_pred_modes([PredId | PredIds], Preds, ModeDefns, InstDefns) -->
{ map__lookup(Preds, PredId, PredDefn) },
{ pred_info_procedures(PredDefn, Procs) },
{ map__keys(Procs, ProcIds) },
find_undef_proc_modes(ProcIds, PredId, Procs, ModeDefns, InstDefns),
find_undef_pred_modes(PredIds, Preds, ModeDefns, InstDefns).
:- pred find_undef_proc_modes(list(proc_id), pred_id, proc_table, mode_table,
user_inst_table, io__state, io__state).
:- mode find_undef_proc_modes(in, in, in, in, in, di, uo) is det.
find_undef_proc_modes([], _PredId, _Procs, _ModeDefns, _InstDefns) --> [].
find_undef_proc_modes([ProcId | ProcIds], PredId, Procs, ModeDefns,
InstDefns) -->
{ map__lookup(Procs, ProcId, ProcDefn) },
{ proc_info_argmodes(ProcDefn, ArgModes) },
{ proc_info_context(ProcDefn, Context) },
find_undef_mode_list(ArgModes, pred(PredId) - Context, ModeDefns,
InstDefns),
find_undef_proc_modes(ProcIds, PredId, Procs, ModeDefns, InstDefns).
%-----------------------------------------------------------------------------%
% Find any undefined insts/modes used in the bodies of other mode
% declarations.
:- pred find_undef_mode_bodies(list(mode_id), mode_table, user_inst_table,
io__state, io__state).
:- mode find_undef_mode_bodies(in, in, in, di, uo) is det.
find_undef_mode_bodies([], _, _) --> [].
find_undef_mode_bodies([ModeId | ModeIds], ModeDefns, InstDefns) -->
{ map__lookup(ModeDefns, ModeId, HLDS_ModeDefn) },
% XXX abstract hlds__mode_defn/5
{ HLDS_ModeDefn = hlds__mode_defn(_, _, Mode, _, Context) },
find_undef_mode_body(Mode, mode(ModeId) - Context, ModeDefns,
InstDefns),
find_undef_mode_bodies(ModeIds, ModeDefns, InstDefns).
% Find any undefined insts/modes used in the given mode definition.
:- pred find_undef_mode_body(hlds__mode_body, mode_error_context,
mode_table, user_inst_table, io__state, io__state).
:- mode find_undef_mode_body(in, in, in, in, di, uo) is det.
find_undef_mode_body(eqv_mode(Mode), ErrorContext, ModeDefns, InstDefns) -->
find_undef_mode(Mode, ErrorContext, ModeDefns, InstDefns).
% Find any undefined modes in a list of modes.
:- pred find_undef_mode_list(list(mode), mode_error_context,
mode_table, user_inst_table, io__state, io__state).
:- mode find_undef_mode_list(in, in, in, in, di, uo) is det.
find_undef_mode_list([], _, _, _) --> [].
find_undef_mode_list([Mode|Modes], ErrorContext, ModeDefns, InstDefns) -->
find_undef_mode(Mode, ErrorContext, ModeDefns, InstDefns),
find_undef_mode_list(Modes, ErrorContext, ModeDefns, InstDefns).
% Find any undefined modes/insts used in a mode.
% The mode itself may be undefined, and also
% any inst arguments may also be undefined.
% (eg. the mode `undef1(undef2, undef3)' should generate 3 errors.)
:- pred find_undef_mode(mode, mode_error_context, mode_table, user_inst_table,
io__state, io__state).
:- mode find_undef_mode(in, in, in, in, di, uo) is det.
find_undef_mode((InstA -> InstB), ErrorContext, _ModeDefns, InstDefns) -->
find_undef_inst(InstA, ErrorContext, InstDefns),
find_undef_inst(InstB, ErrorContext, InstDefns).
find_undef_mode(user_defined_mode(Name, Args), ErrorContext, ModeDefns,
InstDefns) -->
%%% no builtin modes as yet
{ list__length(Args, Arity) },
{ ModeId = Name - Arity },
(
{ map__contains(ModeDefns, ModeId) }
->
[]
;
report_undef_mode(ModeId, ErrorContext)
),
find_undef_inst_list(Args, ErrorContext, InstDefns).
%-----------------------------------------------------------------------------%
% Find any undefined insts used in the bodies of other inst
% declarations.
:- pred find_undef_inst_bodies(list(inst_id), user_inst_table,
io__state, io__state).
:- mode find_undef_inst_bodies(in, in, di, uo) is det.
find_undef_inst_bodies([], _) --> [].
find_undef_inst_bodies([InstId | InstIds], InstDefns) -->
{ map__lookup(InstDefns, InstId, HLDS_InstDefn) },
% XXX abstract hlds__inst_defn/5
{ HLDS_InstDefn = hlds__inst_defn(_, _, Inst, _, Context) },
find_undef_inst_body(Inst, inst(InstId) - Context, InstDefns),
find_undef_inst_bodies(InstIds, InstDefns).
% Find any undefined insts used in the given inst definition.
:- pred find_undef_inst_body(hlds__inst_body, mode_error_context,
user_inst_table, io__state, io__state).
:- mode find_undef_inst_body(in, in, in, di, uo) is det.
find_undef_inst_body(eqv_inst(Inst), ErrorContext, InstDefns) -->
find_undef_inst(Inst, ErrorContext, InstDefns).
find_undef_inst_body(abstract_inst, _, _) --> [].
% Find any undefined insts in a list of insts.
:- pred find_undef_inst_list(list(inst), mode_error_context, user_inst_table,
io__state, io__state).
:- mode find_undef_inst_list(in, in, in, di, uo) is det.
find_undef_inst_list([], _ErrorContext, _InstDefns) --> [].
find_undef_inst_list([Inst|Insts], ErrorContext, InstDefns) -->
find_undef_inst(Inst, ErrorContext, InstDefns),
find_undef_inst_list(Insts, ErrorContext, InstDefns).
% Find any undefined insts used in an inst.
% The inst itself may be undefined, and also
% any inst arguments may also be undefined.
% (eg. the inst `undef1(undef2, undef3)' should generate 3 errors.)
:- pred find_undef_inst(inst, mode_error_context, user_inst_table,
io__state, io__state).
:- mode find_undef_inst(in, in, in, di, uo) is det.
find_undef_inst(free, _, _) --> [].
find_undef_inst(ground, _, _) --> [].
find_undef_inst(inst_var(_), _, _) --> [].
find_undef_inst(bound(BoundInsts), ErrorContext, InstDefns) -->
find_undef_bound_insts(BoundInsts, ErrorContext, InstDefns).
find_undef_inst(defined_inst(InstName), ErrorContext, InstDefns) -->
find_undef_inst_name(InstName, ErrorContext, InstDefns).
find_undef_inst(abstract_inst(Name, Args), ErrorContext, InstDefns) -->
find_undef_inst_name(user_inst(Name, Args), ErrorContext, InstDefns).
find_undef_inst(not_reached, _, _) --> [].
find_undef_inst(free(_), _, _) -->
{ error("compiler generated inst unexpected") }.
:- pred find_undef_inst_name(inst_name, mode_error_context, user_inst_table,
io__state, io__state).
:- mode find_undef_inst_name(in, in, in, di, uo) is det.
find_undef_inst_name(user_inst(Name, Args), ErrorContext, InstDefns) -->
{ list__length(Args, Arity) },
{ InstId = Name - Arity },
(
{ map__contains(InstDefns, InstId) }
->
[]
;
report_undef_inst(InstId, ErrorContext)
),
find_undef_inst_list(Args, ErrorContext, InstDefns).
find_undef_inst_name(unify_inst(_, _, _), _, _) -->
{ error("compiler generated inst unexpected") }.
find_undef_inst_name(merge_inst(_, _), _, _) -->
{ error("compiler generated inst unexpected") }.
find_undef_inst_name(ground_inst(_), _, _) -->
{ error("compiler generated inst unexpected") }.
find_undef_inst_name(typed_ground(_), _, _) -->
{ error("compiler generated inst unexpected") }.
find_undef_inst_name(typed_inst(_,_), _, _) -->
{ error("compiler generated inst unexpected") }.
:- pred find_undef_bound_insts(list(bound_inst), mode_error_context,
user_inst_table, io__state, io__state).
:- mode find_undef_bound_insts(in, in, in, di, uo) is det.
find_undef_bound_insts([], _, _) --> [].
find_undef_bound_insts([functor(_Name, Args) | BoundInsts], ErrorContext,
InstDefns) -->
find_undef_inst_list(Args, ErrorContext, InstDefns),
find_undef_bound_insts(BoundInsts, ErrorContext, InstDefns).
%-----------------------------------------------------------------------------%
:- type mode_error_context == pair(mode_error_context_2, term__context).
:- type mode_error_context_2 ---> inst(inst_id)
; mode(mode_id)
; pred(pred_id).
% Output an error message about an undefined mode
% in the specified context.
:- pred report_undef_mode(mode_id, mode_error_context, io__state, io__state).
:- mode report_undef_mode(in, in, di, uo) is det.
report_undef_mode(ModeId, ErrorContext - Context) -->
io__set_exit_status(1),
prog_out__write_context(Context),
io__write_string("In "),
write_mode_error_context(ErrorContext),
io__write_string(":\n"),
prog_out__write_context(Context),
io__write_string(" error: undefined mode "),
write_mode_id(ModeId),
io__write_string(".\n").
% Output an error message about an undefined inst
% in the specified context.
:- pred report_undef_inst(inst_id, mode_error_context, io__state, io__state).
:- mode report_undef_inst(in, in, di, uo) is det.
report_undef_inst(InstId, ErrorContext - Context) -->
io__set_exit_status(1),
prog_out__write_context(Context),
io__write_string("In "),
write_mode_error_context(ErrorContext),
io__write_string(":\n"),
prog_out__write_context(Context),
io__write_string(" error: undefined inst "),
write_inst_id(InstId),
io__write_string(".\n").
% Output a description of the context where an undefined mode was
% used.
:- pred write_mode_error_context(mode_error_context_2, io__state, io__state).
:- mode write_mode_error_context(in, di, uo) is det.
write_mode_error_context(pred(_PredId)) -->
io__write_string("mode declaration for predicate").
% XXX hlds_out__write_pred_id(PredId).
write_mode_error_context(mode(ModeId)) -->
io__write_string("definition of mode "),
write_mode_id(ModeId).
write_mode_error_context(inst(InstId)) -->
io__write_string("definition of inst "),
write_inst_id(InstId).
%-----------------------------------------------------------------------------%
% Predicates to output inst_ids and mode_ids.
% XXX inst_ids and mode_ids should include the module.
:- pred write_mode_id(mode_id, io__state, io__state).
:- mode write_mode_id(in, di, uo) is det.
write_mode_id(F - N) -->
prog_out__write_sym_name(F),
io__write_string("/"),
io__write_int(N).
% XXX inst_ids should include the module.
:- pred write_inst_id(inst_id, io__state, io__state).
:- mode write_inst_id(in, di, uo) is det.
write_inst_id(F - N) -->
prog_out__write_sym_name(F),
io__write_string("/"),
io__write_int(N).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%