[m-dev.] for review: reordering for existential types [1]

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Jun 23 15:13:39 AEST 1999


On 23-Jun-1999, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:
>  
> > > On 11-Jun-1999, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> > > > Change the order of the passes so that polymorphism comes before
> > > > mode analysis.  This is necessary so that mode analysis can properly
> > > > reorder code involving existential types.
> 
> One other possible problem I noticed is that you moved the code
> to convert higher-order pred constants into lambda expressions
> from modecheck_unify.m into polymorphism.m. What happens if a
> later pass (e.g. deforestation) reruns mode analysis on code which
> constructs a higher-order pred constant?

I'm not entirely sure, so I decided that in the interests of safety
it is probably best to put that code back in modecheck_unify.m
(as well as keeping the copy in polymorphism.m).

----------

Estimated hours taken: 1

compiler/modecheck_unify.m:
	Put back the code for converting unifications with higher-order
	pred constants into lambda expressions, which had been moved to
	polymorphism.m, because it might be needed in case mode analysis is
	rerun after lambda.m has already been run, e.g. during deforestation.

compiler/polymorphism.m:
	Add a comment warning about the code here being duplicated in
	modecheck_unify.m.

Workspace: /home/mercury0/fjh/mercury-other
Index: compiler/modecheck_unify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modecheck_unify.m,v
retrieving revision 1.37.2.3
diff -u -r1.37.2.3 modecheck_unify.m
--- modecheck_unify.m	1999/06/15 15:54:27	1.37.2.3
+++ modecheck_unify.m	1999/06/23 05:01:41
@@ -103,11 +103,132 @@
 
 modecheck_unification(X0, functor(ConsId0, ArgVars0), Unification0,
 			UnifyContext, GoalInfo0, Goal, ModeInfo0, ModeInfo) :-
+	mode_info_get_module_info(ModeInfo0, ModuleInfo0),
 	mode_info_get_var_types(ModeInfo0, VarTypes0),
 	map__lookup(VarTypes0, X0, TypeOfX),
-	modecheck_unify_functor(X0, TypeOfX,
-		ConsId0, ArgVars0, Unification0, UnifyContext,
-		GoalInfo0, Goal, ModeInfo0, ModeInfo).
+	%
+	% We replace any unifications with higher-order pred constants
+	% by lambda expressions.  For example, we replace
+	%
+	%       X = list__append(Y)     % Y::in, X::out
+	%
+	% with
+	%
+	%       X = lambda [A1::in, A2::out] (list__append(Y, A1, A2))
+	%
+	% Normally this is done by polymorphism__process_unify_functor,
+	% but if we're re-modechecking goals after lambda.m has been run
+	% (e.g. for deforestation), then we may need to do it again here.
+	% Note that any changes to this code here will probably need to be
+	% duplicated there too.
+	%
+	(
+		% check if variable has a higher-order type
+		type_is_higher_order(TypeOfX, PredOrFunc, PredArgTypes),
+		ConsId0 = cons(PName, _),
+		% but in case we are redoing mode analysis, make sure
+		% we don't mess with the address constants for type_info
+		% fields created by polymorphism.m
+		Unification0 \= construct(_, code_addr_const(_, _), _, _),
+		Unification0 \= deconstruct(_, code_addr_const(_, _), _, _, _)
+	->
+		%
+		% Create the new lambda-quantified variables
+		%
+		mode_info_get_varset(ModeInfo0, VarSet0),
+		make_fresh_vars(PredArgTypes, VarSet0, VarTypes0,
+				LambdaVars, VarSet, VarTypes),
+		list__append(ArgVars0, LambdaVars, Args),
+		mode_info_set_varset(VarSet, ModeInfo0, ModeInfo1),
+		mode_info_set_var_types(VarTypes, ModeInfo1, ModeInfo2),
+
+		%
+		% Build up the hlds_goal_expr for the call that will form
+		% the lambda goal
+		%
+
+		mode_info_get_predid(ModeInfo0, ThisPredId),
+		module_info_pred_info(ModuleInfo0, ThisPredId, ThisPredInfo),
+		pred_info_typevarset(ThisPredInfo, TVarSet),
+		map__apply_to_list(Args, VarTypes, ArgTypes),
+		(
+			% If we are redoing mode analysis, use the
+			% pred_id and proc_id found before, to avoid aborting
+			% in get_pred_id_and_proc_id if there are multiple
+			% matching procedures.
+			Unification0 = construct(_, 
+				pred_const(PredId0, ProcId0), _, _)
+		->
+			PredId = PredId0,
+			ProcId = ProcId0
+		;
+			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?)
+		pred_info_module(PredInfo, PredModule),
+		unqualify_name(PName, UnqualPName),
+		QualifiedPName = qualified(PredModule, UnqualPName),
+
+		CallUnifyContext = call_unify_context(X0,
+				functor(ConsId0, ArgVars0), UnifyContext),
+		LambdaGoalExpr = call(PredId, ProcId, Args, not_builtin,
+				yes(CallUnifyContext), QualifiedPName),
+
+		%
+		% construct a goal_info for the lambda goal, making sure
+		% to set up the nonlocals field in the goal_info correctly
+		%
+		goal_info_get_nonlocals(GoalInfo0, NonLocals),
+		set__insert_list(NonLocals, LambdaVars, OutsideVars),
+		set__list_to_set(Args, InsideVars),
+		set__intersect(OutsideVars, InsideVars, LambdaNonLocals),
+		goal_info_init(LambdaGoalInfo0),
+		mode_info_get_context(ModeInfo2, Context),
+		goal_info_set_context(LambdaGoalInfo0, Context,
+				LambdaGoalInfo1),
+		goal_info_set_nonlocals(LambdaGoalInfo1, LambdaNonLocals,
+				LambdaGoalInfo),
+		LambdaGoal = LambdaGoalExpr - LambdaGoalInfo,
+
+		%
+		% work out the modes of the introduced lambda variables
+		% and the determinism of the lambda goal
+		%
+		proc_info_argmodes(ProcInfo, ArgModes),
+		list__length(ArgVars0, Arity),
+		( list__drop(Arity, ArgModes, LambdaModes0) ->
+			LambdaModes = LambdaModes0
+		;
+			error("modecheck_unification: list__drop failed")
+		),
+		proc_info_declared_determinism(ProcInfo, MaybeDet),
+		( MaybeDet = yes(Det) ->
+			LambdaDet = Det
+		;
+			error("Sorry, not implemented: determinism inference for higher-order predicate terms")
+		),
+
+		%
+		% construct the lambda expression, and then go ahead
+		% and modecheck this unification in its new form
+		%
+		Functor0 = lambda_goal(PredOrFunc, ArgVars0, LambdaVars, 
+				LambdaModes, LambdaDet, LambdaGoal),
+		modecheck_unification( X0, Functor0, Unification0, UnifyContext,
+				GoalInfo0, Goal, ModeInfo2, ModeInfo)
+	;
+		%
+		% It's not a higher-order pred unification - just
+		% call modecheck_unify_functor to do the ordinary thing.
+		%
+		modecheck_unify_functor(X0, TypeOfX,
+			ConsId0, ArgVars0, Unification0, UnifyContext,
+			GoalInfo0, Goal, ModeInfo0, ModeInfo)
+	).
 
 modecheck_unification(X, 
 		lambda_goal(PredOrFunc, ArgVars, Vars, Modes0, Det, Goal0),
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.163.2.4
diff -u -r1.163.2.4 polymorphism.m
--- polymorphism.m	1999/06/21 14:56:57	1.163.2.4
+++ polymorphism.m	1999/06/23 05:04:25
@@ -1307,6 +1307,11 @@
 	% lambda.m will (I hope) turn the lambda expression
 	% back into a higher-order pred constant again.
 	%
+	% Note that this transformation is also done by modecheck_unify.m,
+	% in case we are rerunning mode analysis after lambda.m has already
+	% been run; any changes to the code here will also need to be
+	% duplicated there.
+	%
 
 		% check if variable has a higher-order type
 		type_is_higher_order(TypeOfX, PredOrFunc, PredArgTypes),

-- 
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.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list