diff for review: overload resolution for higher-order terms

Fergus Henderson fjh at cs.mu.oz.au
Sat Mar 22 05:55:28 AEDT 1997


Hi,

Can someone please review this change?

Estimated Hours: 4

Fix a bug: use the types to resolve overloading for higher-order terms.
This avoids a software error in get_pred_and_proc_id when you try to
take the address of an overloaded predicate or function, e.g. `<',
without using an explicit module qualifier.

hlds_module.m:
	Change get_pred_and_proc_id to handle overload resolution.
	(Also, simplify the code by splitting out `get_proc_id'
	as a new subroutine.)

typecheck.m:
	Export new pred `typecheck__resolve_overloading'.  Previously the
	code for this was part of `typecheck__resolve_pred_overloading'.

intermod.m:
	Change call to get_pred_and_proc_id to match its new interface.
	Use `typecheck__resolve_overloading' rather than
	`typecheck__find_matching_pred_ids'.
	(Also, a few stylistic changes: add some documentation and
	rearrange the code a little.)

modecheck_unify.m:
	Change call to get_pred_and_proc_id to match its new interface.

cvs diff: Diffing .
Index: hlds_module.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_module.m,v
retrieving revision 1.17
diff -u -r1.17 hlds_module.m
--- hlds_module.m	1997/03/06 05:09:03	1.17
+++ hlds_module.m	1997/03/21 17:35:40
@@ -29,6 +29,7 @@
 
 :- import_module hlds_data, hlds_out, prog_data, prog_util, shapes.
 :- import_module require, int, string, list, map, set, std_util.
+:- import_module typecheck.
 
 %-----------------------------------------------------------------------------%
 
@@ -1012,7 +1013,7 @@
 	% Get the pred_id and proc_id matching a higher-order term with
 	% the given argument types, aborting with an error if none is
 	% found.
-:- pred get_pred_id_and_proc_id(sym_name, arity, pred_or_func, list(type),
+:- pred get_pred_id_and_proc_id(sym_name, pred_or_func, tvarset, list(type),
 				module_info, pred_id, proc_id).
 :- mode get_pred_id_and_proc_id(in, in, in, in, in, out, out) is det.
 
@@ -1421,74 +1422,66 @@
 				Func_N_Index, Func_NA_Index, Func_MNA_Index).
 
 
-get_pred_id_and_proc_id(SymName, Arity, PredOrFunc, PredArgTypes, ModuleInfo,
+get_pred_id_and_proc_id(SymName, PredOrFunc, TVarSet, ArgTypes, ModuleInfo,
 			PredId, ProcId) :-
-	unqualify_name(SymName, Name),
-	list__length(PredArgTypes, PredArity),
-	TotalArity is Arity + PredArity,
 	module_info_get_predicate_table(ModuleInfo, PredicateTable),
+	list__length(ArgTypes, Arity),
 	(
-	    predicate_table_search_pf_sym_arity(PredicateTable,
-		PredOrFunc, SymName, TotalArity, PredIds)
+		predicate_table_search_pf_sym_arity(PredicateTable,
+			PredOrFunc, SymName, Arity, PredIds),
+		typecheck__find_matching_pred_id(PredIds, ModuleInfo,
+			TVarSet, ArgTypes, PredId0, _PredName)
 	->
-	    (
-		PredIds = [PredId0]
-	    ->
 		PredId = PredId0,
-		predicate_table_get_preds(PredicateTable, Preds),
-		map__lookup(Preds, PredId, PredInfo),
-		pred_info_procedures(PredInfo, Procs),
-		map__keys(Procs, ProcIds),
-		( ProcIds = [ProcId0] ->
-		    ProcId = ProcId0
-		; ProcIds = [] ->
-		    hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncStr),
-		    string__int_to_string(TotalArity, TotalArityString),
-		    string__append_list([
-			    "cannot take address of ", PredOrFuncStr,
-			    "\n`", Name, "/", TotalArityString,
-			    "' with no modes.\n",
-			    "(Sorry, confused by earlier errors ",
-			    	"-- bailing out.)"],
-			    Message),
-		    error(Message)
-		;
-		    hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncStr),
-		    string__int_to_string(TotalArity, TotalArityString),
-		    string__append_list([
-			    "sorry, not implemented: ",
-			    "taking address of ", PredOrFuncStr,
-			    "\n`", Name, "/", TotalArityString,
-			    "' with multiple modes.\n",
-			    "(use an explicit lambda expression instead)"],
-			    Message),
-		    error(Message)
-		)
-	    ;
-	        % Ambiguous pred or func.
-		% cons_id ought to include the module prefix, so
-		% that we could use predicate_table__search_m_n_a to 
-		% prevent this from happening
-	        hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncStr),
-	        string__int_to_string(TotalArity, TotalArityString),
+		get_proc_id(PredicateTable, PredId, ProcId)
+	;
+		% Undefined/invalid pred or func.
+		% the type-checker should ensure that this never happens
+		hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncStr),
+		unqualify_name(SymName, Name),
+		string__int_to_string(Arity, ArityString),
 		string__append_list(
 			["get_pred_id_and_proc_id: ",
-			"ambiguous ", PredOrFuncStr,
-		        "\n`", Name, "/", TotalArityString, "'"],
+			"undefined/invalid ", PredOrFuncStr,
+			"\n`", Name, "/", ArityString, "'"],
 			Msg),
 		error(Msg)
-	    )
+	).
+
+:- pred get_proc_id(predicate_table, pred_id, proc_id).
+:- mode get_proc_id(in, in, out) is det.
+
+get_proc_id(PredicateTable, PredId, ProcId) :-
+	predicate_table_get_preds(PredicateTable, Preds),
+	map__lookup(Preds, PredId, PredInfo),
+	pred_info_procedures(PredInfo, Procs),
+	map__keys(Procs, ProcIds),
+	( ProcIds = [ProcId0] ->
+		ProcId = ProcId0
 	;
-	    % Undefined/invalid pred or func.
-	    % the type-checker should ensure that this never happens
-	    hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncStr),
-	    string__int_to_string(TotalArity, TotalArityString),
-	    string__append_list(
-		["get_pred_id_and_proc_id: ",
-		"undefined/invalid ", PredOrFuncStr,
-		"\n`", Name, "/", TotalArityString, "'"],
-		Msg),
-	    error(Msg)
+		pred_info_name(PredInfo, Name),
+		pred_info_get_is_pred_or_func(PredInfo, PredOrFunc),
+		pred_info_arity(PredInfo, Arity),
+		hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncStr),
+		string__int_to_string(Arity, ArityString),
+		( ProcIds = [] ->
+			string__append_list([
+				"cannot take address of ", PredOrFuncStr,
+				"\n`", Name, "/", ArityString,
+				"' with no modes.\n",
+				"(Sorry, confused by earlier errors -- ",
+				"bailing out.)"],
+				Message)
+		;
+			string__append_list([
+				"sorry, not implemented: ",
+				"taking address of ", PredOrFuncStr,
+				"\n`", Name, "/", ArityString,
+				"' with multiple modes.\n",
+				"(use an explicit lambda expression instead)"],
+				Message)
+		),
+		error(Message)
 	).
 
 %-----------------------------------------------------------------------------%
Index: intermod.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/intermod.m,v
retrieving revision 1.19
diff -u -r1.19 intermod.m
--- intermod.m	1997/03/06 05:09:12	1.19
+++ intermod.m	1997/03/21 18:18:19
@@ -481,10 +481,7 @@
 		{ DoWrite = yes }
 	).
 
-	% Resolve overloading and module qualify function calls and
-	% higher-order predicate constants in a unify_rhs.
-	% This has to wait until I implement module qualification of
-	% functions.
+	% Resolve overloading and module qualify everything in a unify_rhs.
 :- pred intermod__module_qualify_unify_rhs(var::in, unify_rhs::in,
 		unify_rhs::out, bool::out, intermod_info::in,
 		intermod_info::out) is det.
@@ -502,8 +499,10 @@
 	intermod__gather_proc_modes(ModuleInfo, ModeDefns,
 				UserInstDefns, Modes).
 
-	% Check if the functor is actually a function call or a higher-order
-	% pred constant. If so, module qualify.
+	% Check if the functor is a function call, a higher-order
+	% term, or an unqualified symbol. If so, module qualify.
+	% For function calls and higher-order terms, call intermod__add_proc
+	% so that the predicate or function will be exported if necessary.
 intermod__module_qualify_unify_rhs(LVar, functor(Functor0, Vars),
 				functor(Functor, Vars), DoWrite) -->
 	intermod_info_get_module_info(ModuleInfo),
@@ -511,40 +510,77 @@
 	intermod_info_get_tvarset(TVarSet),
 	intermod_info_get_var_types(VarTypes),
 	(
-		{ 
-			Functor0 = cons(QualifiedFuncName, Arity),
-			QualifiedFuncName = qualified(FuncModule, FuncName),
-			predicate_table_search_func_m_n_a(PredTable,
-				FuncModule, FuncName, Arity, [PredId])
+		%
+		% Is it a module-qualified function call?
+		%
+		{ Functor0 = cons(qualified(FuncModule, FuncName), Arity) },
+		{ predicate_table_search_func_m_n_a(PredTable,
+				FuncModule, FuncName, Arity, PredIds) }
+	->
+		%
+		% Yes, it is a module-qualified function call.
+		% Make sure that the called function will be exported.
+		%
+		( { PredIds = [PredId] } ->
+			intermod_info_add_proc(PredId, DoWrite)
 		;
-			Functor0 = cons(unqualified(FuncName), Arity),
-			predicate_table_search_func_name_arity(PredTable,
-					FuncName, Arity, PredIds),
-			list__append(Vars, [LVar], FuncArgs),
-			map__apply_to_list(FuncArgs, VarTypes, ArgTypes),
-			typecheck__find_matching_pred_id(PredIds, ModuleInfo,
-				TVarSet, ArgTypes, PredId, QualifiedFuncName)
-		}
+			% there should be at most one function
+			% with a given module, name, and arity
+			{ error("intermod.m: func_m_n_a not unique") }
+		),
+		{ Functor = Functor0 }
+	;
+		%
+		% Is it an unqualified function call?
+		%
+		{ Functor0 = cons(unqualified(FuncName), Arity) },
+		{ predicate_table_search_func_name_arity(PredTable,
+				FuncName, Arity, PredIds) }
 	->
-			% The unification is really a function call
+		%
+		% Yes, it is an unqualified function call.
+		% Module-qualify it.
+		% Make sure that the called function will be exported.
+		%
+		{ list__append(Vars, [LVar], FuncArgs) },
+		{ typecheck__resolve_overloading(ModuleInfo,
+			FuncArgs, VarTypes, TVarSet, PredIds,
+			QualifiedFuncName, PredId) },
 		{ Functor = cons(QualifiedFuncName, Arity) },
 		intermod_info_add_proc(PredId, DoWrite)
 	;
-		intermod_info_get_var_types(VarTypes),
+		%
+		% Is this a higher-order predicate or higher-order function
+		% term?
+		%
 		{ Functor0 = cons(PredName, Arity) },
+		intermod_info_get_var_types(VarTypes),
 		{ map__lookup(VarTypes, LVar, LVarType) },
 		{ type_is_higher_order(LVarType, PredOrFunc, PredArgTypes) }
 	->
-			% The unification creates a higher-order pred constant.
-		{ get_pred_id_and_proc_id(PredName, Arity, PredOrFunc,
-			PredArgTypes, ModuleInfo, PredId, _ProcId) },
-		{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
-		{ pred_info_module(PredInfo, Module) },
-		{ unqualify_name(PredName, UnqualPredName) },
-		{ QualifiedPredName = qualified(Module, UnqualPredName) },
-		{ Functor = cons(QualifiedPredName, Arity) },
-		intermod_info_add_proc(PredId, DoWrite)
+		%
+		% Yes, the unification creates a higher-order term.
+		% Make sure that the predicate/function is exported.
+		%
+		{ map__apply_to_list(Vars, VarTypes, Types) },
+		{ list__append(PredArgTypes, Types, ArgTypes) },
+		{ get_pred_id_and_proc_id(PredName, PredOrFunc,
+			TVarSet, ArgTypes, ModuleInfo, PredId, _ProcId) },
+		intermod_info_add_proc(PredId, DoWrite),
+		%
+		% Module-qualify it, if necessary.
+		%
+		{ PredName = unqualified(UnqualPredName) ->
+			predicate_module(ModuleInfo, PredId, Module),
+			QualifiedPredName = qualified(Module, UnqualPredName),
+			Functor = cons(QualifiedPredName, Arity)
+		;
+			Functor = Functor0
+		}
 	;
+		%
+		% Is it an unqualified functor symbol?
+		%
 		{ Functor0 = cons(unqualified(ConsName), ConsArity) },
 		{ map__lookup(VarTypes, LVar, VarType) },
 		{ type_to_type_id(VarType, TypeId, _) },
Index: modecheck_unify.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/modecheck_unify.m,v
retrieving revision 1.11
diff -u -r1.11 modecheck_unify.m
--- modecheck_unify.m	1997/03/06 05:09:37	1.11
+++ modecheck_unify.m	1997/03/21 18:05:42
@@ -222,7 +222,7 @@
 	% back into a higher-order pred constant again.
 	%
 
-		% check if variable has a higher-order pred type
+		% check if variable has a higher-order type
 		type_is_higher_order(TypeOfX, PredOrFunc, PredArgTypes),
 		ConsId = cons(PName, _),
 		% but in case we are redoing mode analysis, make sure
@@ -246,11 +246,15 @@
 		% the lambda goal
 		%
 
-		get_pred_id_and_proc_id(PName, Arity, PredOrFunc,
-			PredArgTypes, ModuleInfo0, PredId, ProcId),
+		module_info_pred_info(ModuleInfo0, ThisPredId, ThisPredInfo),
+		pred_info_typevarset(ThisPredInfo, TVarSet),
+		map__apply_to_list(Args, VarTypes, ArgTypes),
+		get_pred_id_and_proc_id(PName, PredOrFunc, TVarSet, ArgTypes,
+			ModuleInfo0, PredId, ProcId),
+		module_info_pred_proc_info(ModuleInfo0, PredId, ProcId,
+					PredInfo, ProcInfo),
 
 		% module-qualify the pred name (is this necessary?)
-		module_info_pred_info(ModuleInfo0, PredId, PredInfo),
 		pred_info_module(PredInfo, PredModule),
 		unqualify_name(PName, UnqualPName),
 		QualifiedPName = qualified(PredModule, UnqualPName),
@@ -277,8 +281,6 @@
 		% work out the modes of the introduced lambda variables
 		% and the determinism of the lambda goal
 		%
-		module_info_pred_proc_info(ModuleInfo0, PredId, ProcId,
-					_PredInfo, ProcInfo),
 		proc_info_argmodes(ProcInfo, ArgModes),
 		( list__drop(Arity, ArgModes, LambdaModes0) ->
 			LambdaModes = LambdaModes0
Index: typecheck.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/typecheck.m,v
retrieving revision 1.189
diff -u -r1.189 typecheck.m
--- typecheck.m	1997/02/26 09:47:55	1.189
+++ typecheck.m	1997/03/21 18:16:16
@@ -142,12 +142,28 @@
 
 
 	% Find a predicate which matches the given name and argument types.
+	% Abort if there is no matching pred.
+	% Abort if there are multiple matching preds.
 
 :- pred typecheck__resolve_pred_overloading(module_info, list(var),
 			map(var, type), tvarset, sym_name, sym_name, pred_id).
 :- mode typecheck__resolve_pred_overloading(in, in, in, in,
 			in, out, out) is det.
 
+	% Find a predicate or function from the list of pred_ids
+	% which matches the given name and argument types.
+	% Abort if there is no matching pred.
+	% Abort if there are multiple matching preds.
+
+:- pred typecheck__resolve_overloading(module_info, list(var), map(var, type),
+				tvarset, list(pred_id), sym_name, pred_id).
+:- mode typecheck__resolve_overloading(in, in, in, in, in, out, out) is det.
+
+	% Find a predicate or function from the list of pred_ids
+	% which matches the given name and argument types.
+	% Fail if there is no matching pred.
+	% Abort if there are multiple matching preds.
+
 :- pred typecheck__find_matching_pred_id(list(pred_id), module_info,
 			tvarset, list(type), pred_id, sym_name).
 :- mode typecheck__find_matching_pred_id(in, in, in, in, out, out) is semidet.
@@ -899,7 +915,11 @@
 	;
 		PredIds = []
 	),
+	typecheck__resolve_overloading(ModuleInfo, Args, VarTypes, TVarSet,
+			 PredIds, PredName, PredId).
 
+typecheck__resolve_overloading(ModuleInfo, Args, VarTypes, TVarSet, PredIds,
+		 PredName, PredId) :-
 	%
 	% Check if there any of the candidate pred_ids
 	% have argument/return types which subsume the actual
cvs diff: Diffing notes

-- 
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