diff: bug fix

Simon TAYLOR stayl at students.cs.mu.oz.au
Fri May 23 11:21:18 AEST 1997


Hi DJ,

Could you please review this.

Simon

Estimated hours taken: 1

Fix bugs where undefined modes were causing map__lookup failures.

compiler/mode_util.m
	Add mode_get_insts_semidet, which fails instead of aborting
	if the mode is undefined.

compiler/make_hlds.m
	Use mode_get_insts_semidet instead of mode_get_insts when 
	matching pragma c_code modes.

compiler/mercury_compile.m
compiler/typecheck.m
	Pass through whether there were undefined modes into typecheck.m.
	Only attempt to propagate type information into modes if there
	were no undefined mode errors.

tests/invalid/Mmake
tests/invalid/undef_mode.m
tests/invalid/undef_mode.err_exp
	Add a test case.	

Index: compiler/make_hlds.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/make_hlds.m,v
retrieving revision 1.229
diff -u -r1.229 make_hlds.m
--- make_hlds.m	1997/05/05 11:17:15	1.229
+++ make_hlds.m	1997/05/23 01:10:17
@@ -1789,8 +1789,10 @@
 
 mode_list_matches([], [], _).
 mode_list_matches([Mode1 | Modes1], [Mode2 | Modes2], ModuleInfo) :-
-	mode_get_insts(ModuleInfo, Mode1, Inst1, Inst2),
-	mode_get_insts(ModuleInfo, Mode2, Inst1, Inst2),
+	% Use mode_get_insts_semidet instead of mode_get_insts to avoid
+	% aborting if there are undefined modes.
+	mode_get_insts_semidet(ModuleInfo, Mode1, Inst1, Inst2),
+	mode_get_insts_semidet(ModuleInfo, Mode2, Inst1, Inst2),
 	mode_list_matches(Modes1, Modes2, ModuleInfo).
 
 %-----------------------------------------------------------------------------%
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/mercury_compile.m,v
retrieving revision 1.37
diff -u -r1.37 mercury_compile.m
--- mercury_compile.m	1997/05/21 02:13:33	1.37
+++ mercury_compile.m	1997/05/21 07:35:09
@@ -379,7 +379,7 @@
 	    %
 	    % Next typecheck the clauses.
 	    %
-	    typecheck(HLDS1, HLDS3, FoundTypeError), !,
+	    typecheck(FoundUndefModeError, HLDS1, HLDS3, FoundTypeError), !,
 	    ( { FoundTypeError = yes } ->
 		maybe_write_string(Verbose,
 			"% Program contains type error(s).\n"),
Index: compiler/mode_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/mode_util.m,v
retrieving revision 1.86
diff -u -r1.86 mode_util.m
--- mode_util.m	1997/05/05 11:17:19	1.86
+++ mode_util.m	1997/05/16 05:25:37
@@ -19,11 +19,16 @@
 :- import_module bool, list.
 
 	% mode_get_insts returns the initial instantiatedness and
-	% the final instantiatedness for a given mode.
+	% the final instantiatedness for a given mode, aborting
+	% if the mode is undefined.
 	%
 :- pred mode_get_insts(module_info, mode, inst, inst).
 :- mode mode_get_insts(in, in, out, out) is det.
 
+	% a version of mode_get_insts which fails if the mode is undefined
+:- pred mode_get_insts_semidet(module_info, mode, inst, inst).
+:- mode mode_get_insts_semidet(in, in, out, out) is semidet.
+
 	% a mode is considered input if the initial inst is bound
 :- pred mode_is_input(module_info, mode).
 :- mode mode_is_input(in, in) is semidet.
@@ -1296,17 +1301,28 @@
 	% mode_get_insts returns the initial instantiatedness and
 	% the final instantiatedness for a given mode.
 
-mode_get_insts(_ModuleInfo, (InitialInst -> FinalInst), InitialInst, FinalInst).
-mode_get_insts(ModuleInfo, user_defined_mode(Name, Args), Initial, Final) :-
+mode_get_insts_semidet(_ModuleInfo, (InitialInst -> FinalInst), 
+		InitialInst, FinalInst).
+mode_get_insts_semidet(ModuleInfo, user_defined_mode(Name, Args), 
+		Initial, Final) :-
 	list__length(Args, Arity),
 	module_info_modes(ModuleInfo, Modes),
 	mode_table_get_mode_defns(Modes, ModeDefns),
-	map__lookup(ModeDefns, Name - Arity, HLDS_Mode),
+	map__search(ModeDefns, Name - Arity, HLDS_Mode),
 	HLDS_Mode = hlds_mode_defn(_VarSet, Params, ModeDefn, _Cond,
 						_Context, _Status),
 	ModeDefn = eqv_mode(Mode0),
 	mode_substitute_arg_list(Mode0, Params, Args, Mode),
 	mode_get_insts(ModuleInfo, Mode, Initial, Final).
+
+mode_get_insts(ModuleInfo, Mode, Inst1, Inst2) :-
+	( mode_get_insts_semidet(ModuleInfo, Mode, Inst1a, Inst2a) ->
+		Inst1 = Inst1a,
+		Inst2 = Inst2a
+	;
+		error("mode_get_insts_semidet failed")
+	).
+
 
 	% mode_substitute_arg_list(Mode0, Params, Args, Mode) is true
 	% iff Mode is the mode that results from substituting all
Index: compiler/typecheck.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/typecheck.m,v
retrieving revision 1.203
diff -u -r1.203 typecheck.m
--- typecheck.m	1997/05/07 07:52:19	1.203
+++ typecheck.m	1997/05/21 07:50:29
@@ -112,19 +112,20 @@
 :- import_module hlds_module, hlds_pred.
 :- import_module bool, io.
 
-:- pred typecheck(module_info, module_info, bool, io__state, io__state).
-:- mode typecheck(in, out, out, di, uo) is det.
+:- pred typecheck(bool, module_info, module_info, bool, io__state, io__state).
+:- mode typecheck(in, in, out, out, di, uo) is det.
 
 /*
-	Formally, typecheck(Module0, Module, FoundError, IO0, IO) is
+	Formally, typecheck(ModeError, Module0, Module, FoundError, IO0, IO) is
 	intended to be true iff Module is Module0 annotated with the
 	variable typings that result from the process of type-checking,
 	FoundError is `yes' if Module0 contains any type errors and `no'
 	otherwise, and IO is the io__state that results from IO0 after
 	printing out appropriate error messages for the type errors in
-	Module0, if any.
+	Module0, if any. ModeError should be true if any undefined modes	
+	were found by previous passes.
 
-	Informally, typecheck(Module0, Module, FoundError, IO0, IO) 
+	Informally, typecheck(PropModes, Module0, Module, FoundError, IO0, IO) 
 	type-checks Module0 and annotates it with variable typings
 	(returning the result in Module), prints out appropriate error
 	messages, and sets FoundError to `yes' if it finds any errors
@@ -135,6 +136,8 @@
 	and not at the start of modecheck because modecheck may be
 	reinvoked after HLDS transformations. Any transformation that
 	needs typechecking should work with the clause_info structure.
+	Type information is also propagated into the modes of procedures
+	by this pass if the ModeError parameter is no. 
 */
 
 
@@ -173,14 +176,14 @@
 
 	% XXX need to pass FoundError to all steps
 
-typecheck(Module0, Module, FoundError) -->
+typecheck(ModeError, Module0, Module, FoundError) -->
 	globals__io_lookup_bool_option(statistics, Statistics),
 	globals__io_lookup_bool_option(verbose, Verbose),
 	io__stderr_stream(StdErr),
 	io__set_output_stream(StdErr, OldStream),
 
 	maybe_write_string(Verbose, "% Type-checking clauses...\n"),
-	check_pred_types(Module0, Module, FoundError),
+	check_pred_types(ModeError, Module0, Module, FoundError),
 	maybe_report_stats(Statistics),
 
 	io__set_output_stream(OldStream, _).
@@ -189,24 +192,25 @@
 
 	% Type-check the code for all the predicates in a module.
 
-:- pred check_pred_types(module_info, module_info, bool, io__state, io__state).
-:- mode check_pred_types(in, out, out, di, uo) is det.
+:- pred check_pred_types(bool, module_info, module_info, bool,
+		io__state, io__state).
+:- mode check_pred_types(in, in, out, out, di, uo) is det.
 
-check_pred_types(Module0, Module, FoundError) -->
+check_pred_types(ModeError, Module0, Module, FoundError) -->
 	{ module_info_predids(Module0, PredIds) },
-	typecheck_to_fixpoint(PredIds, Module0, Module, FoundError),
+	typecheck_to_fixpoint(PredIds, ModeError, Module0, Module, FoundError),
 	write_inference_messages(PredIds, Module).
 
 	% Repeatedly typecheck the code for a group of predicates
 	% until a fixpoint is reached, or until some errors are detected.
 
-:- pred typecheck_to_fixpoint(list(pred_id), module_info, module_info, bool,
-			io__state, io__state).
-:- mode typecheck_to_fixpoint(in, in, out, out, di, uo) is det.
-
-typecheck_to_fixpoint(PredIds, Module0, Module, FoundError) -->
-	typecheck_pred_types_2(PredIds, Module0, Module1, no, FoundError1, no,
-		Changed),
+:- pred typecheck_to_fixpoint(list(pred_id), bool, module_info, 
+		module_info, bool, io__state, io__state).
+:- mode typecheck_to_fixpoint(in, in, in, out, out, di, uo) is det.
+
+typecheck_to_fixpoint(PredIds, ModeError, Module0, Module, FoundError) -->
+	typecheck_pred_types_2(PredIds, ModeError, 
+		Module0, Module1, no, FoundError1, no, Changed),
 	( { Changed = no ; FoundError1 = yes } ->
 		{ Module = Module1 },
 		{ FoundError = FoundError1 }
@@ -217,20 +221,22 @@
 		;
 			[]
 		),
-		typecheck_to_fixpoint(PredIds, Module1, Module, FoundError)
+		typecheck_to_fixpoint(PredIds, ModeError,
+			Module1, Module, FoundError)
 	).
 
 %-----------------------------------------------------------------------------%
 
 	% Iterate over the list of pred_ids in a module.
 
-:- pred typecheck_pred_types_2(list(pred_id), module_info, module_info,
+:- pred typecheck_pred_types_2(list(pred_id), bool, module_info, module_info,
 	bool, bool, bool, bool, io__state, io__state).
-:- mode typecheck_pred_types_2(in, in, out, in, out, in, out, di, uo) is det.
+:- mode typecheck_pred_types_2(in, in, in, out,
+	in, out, in, out, di, uo) is det.
 
-typecheck_pred_types_2([], ModuleInfo, ModuleInfo, Error, Error,
-			Changed, Changed) --> [].
-typecheck_pred_types_2([PredId | PredIds],
+typecheck_pred_types_2([], _, ModuleInfo, ModuleInfo, 
+			Error, Error, Changed, Changed) --> [].
+typecheck_pred_types_2([PredId | PredIds], ModeError, 
 		ModuleInfo0, ModuleInfo, Error0, Error, Changed0, Changed) -->
 	{ module_info_preds(ModuleInfo0, Preds0) },
 	{ map__lookup(Preds0, PredId, PredInfo0) },
@@ -255,21 +261,11 @@
 		Changed2 = Changed0
 		}
 	;
-		typecheck_pred_type(PredId, PredInfo0, ModuleInfo0,
-			MaybePredInfo, Changed1),
+		typecheck_pred_type(PredId, PredInfo0, ModeError, 
+			ModuleInfo0, MaybePredInfo, Changed1),
 		{
-			MaybePredInfo = yes(PredInfo1),
+			MaybePredInfo = yes(PredInfo),
 			Error1 = Error0,
-
-			% 
-			% Ensure that all constructors occurring in predicate 
-			% mode declarations are module qualified.
-			% 
-			pred_info_arg_types(PredInfo1, _, ArgTypes),
-			pred_info_procedures(PredInfo1, Procs1),
-			typecheck_propagate_type_info_into_proc_modes(
-			    ModuleInfo0, ProcIds, ArgTypes, Procs1, Procs),
-			pred_info_set_procedures(PredInfo1, Procs, PredInfo),
 			map__det_update(Preds0, PredId, PredInfo, Preds),
 			module_info_set_preds(ModuleInfo0, Preds, ModuleInfo1)
 		;
@@ -280,8 +276,43 @@
 		},
 		{ bool__or(Changed0, Changed1, Changed2) }
 	),
-	typecheck_pred_types_2(PredIds, ModuleInfo1, ModuleInfo, Error1, Error,
-		Changed2, Changed).
+	typecheck_pred_types_2(PredIds, ModeError, ModuleInfo1, 
+		ModuleInfo, Error1, Error, Changed2, Changed).
+
+:- pred typecheck_pred_type(pred_id, pred_info, bool, module_info,
+	maybe(pred_info), bool, io__state, io__state).
+:- mode typecheck_pred_type(in, in, in, in, out, out, di, uo) is det.
+
+typecheck_pred_type(PredId, PredInfo0, ModeError, ModuleInfo,
+		MaybePredInfo, Changed, IOState0, IOState) :-
+	typecheck_pred_type_2(PredId, PredInfo0, ModuleInfo, MaybePredInfo0,
+		Changed, IOState0, IOState),
+	(
+		MaybePredInfo0 = no,
+		MaybePredInfo = no
+	;
+		MaybePredInfo0 = yes(PredInfo1),
+
+		( ModeError = no ->
+			% 
+			% Copy clauses to procs, then ensure that all 
+			% constructors occurring in predicate mode 
+			% declarations are module qualified, unless undefined
+			% modes were found by an earlier pass.
+			% 
+			maybe_add_default_mode(PredInfo1, PredInfo2),
+			copy_clauses_to_procs(PredInfo2, PredInfo3),
+			pred_info_arg_types(PredInfo3, _, ArgTypes),
+			pred_info_procedures(PredInfo3, Procs1),
+			pred_info_procids(PredInfo3, ProcIds),
+			typecheck_propagate_type_info_into_proc_modes(
+				ModuleInfo, ProcIds, ArgTypes, Procs1, Procs),
+			pred_info_set_procedures(PredInfo3, Procs, PredInfo)
+		;
+			PredInfo = PredInfo1
+		),
+		MaybePredInfo = yes(PredInfo)
+	).
 
 :- pred typecheck_propagate_type_info_into_proc_modes(module_info,
 		list(proc_id), list(type), proc_table, proc_table).
@@ -299,24 +330,6 @@
 	map__det_update(Procs0, ProcId, ProcInfo, Procs1),
 	typecheck_propagate_type_info_into_proc_modes(ModuleInfo, ProcIds,
 		ArgTypes, Procs1, Procs).
-
-:- pred typecheck_pred_type(pred_id, pred_info, module_info,
-	maybe(pred_info), bool, io__state, io__state).
-:- mode typecheck_pred_type(in, in, in, out, out, di, uo) is det.
-
-typecheck_pred_type(PredId, PredInfo0, ModuleInfo, MaybePredInfo, Changed,
-		IOState0, IOState) :-
-	typecheck_pred_type_2(PredId, PredInfo0, ModuleInfo, MaybePredInfo0,
-		Changed, IOState0, IOState),
-	(
-		MaybePredInfo0 = no,
-		MaybePredInfo = no
-	;
-		MaybePredInfo0 = yes(PredInfo1),
-		maybe_add_default_mode(PredInfo1, PredInfo2),
-		copy_clauses_to_procs(PredInfo2, PredInfo),
-		MaybePredInfo = yes(PredInfo)
-	).
 
 :- pred typecheck_pred_type_2(pred_id, pred_info, module_info,
 	maybe(pred_info), bool, io__state, io__state).
Index: tests/invalid/Mmake
===================================================================
RCS file: /home/staff/zs/imp/tests/invalid/Mmake,v
retrieving revision 1.15
diff -u -r1.15 Mmake
--- Mmake	1997/04/27 05:28:46	1.15
+++ Mmake	1997/05/22 23:22:36
@@ -27,6 +27,7 @@
 	qual_basic_test2.m \
 	type_loop.m \
 	undef_lambda_mode.m \
+	undef_mode.m \
 	undef_type.m
 
 # we do not yet pass the following tests:



More information about the developers mailing list