[m-rev.] Re: for review: default modes for higher-order func insts

David Overton dmo at cs.mu.OZ.AU
Wed Oct 10 14:39:47 AEST 2001


On Fri, Aug 03, 2001 at 09:44:37PM +1000, Fergus Henderson wrote:
> On 03-Aug-2001, David Overton <dmo at cs.mu.OZ.AU> wrote:
> > Implement a change to the mode system suggested by Ralph Becket to make use of
> > higher order functions a bit easier.
> 
> There should really be some documentation of this in the Mercury language
> reference manual.

Documentation is still to come.  I would like to get this committed
though, so that people like Ralph and Michael who have been asking for
it can try it out.

> 
> The most difficult part of this diff to review is all of the places that
> you *didn't* change.  There's a high likelihood of some existing code
> not doing the right thing for the new semantics of `ground'.
> 
> However, I have done my best.  One thing I noticed is that the code
> for propagating higher-order types into insts in mode_util.m isn't
> needed anymore, and should be deleted.

I will make this a separate change.

> But because of the difficulty
> in reviewing, the change will need careful testing.
> 
> > compiler/inst_match.m:
> > 	In 'inst_matches_initial' and 'inst_matches_final', ensure that higher
> > 	order inst information is not lost from non-standard function insts.
> > 	Also allow 'inst_matches_{initial,final,binding}' to succeed
> > 	where the first inst is a standard function inst and the
> > 	second is ground.
> 
> I think you should also add some comments to inst_is_ground explaining
> what it does for non-standard function insts, and why.  Currently it
> succeeds, which I think is the right thing for most callers, but not for
> all.  There is at least one place where this issue with inst_is_ground
> leads to a bug with your current diff because of somewhere that
> you didn't change.

done.

> 
> You need go through every call to inst_is_ground and see whether it
> is OK for each call to succeed for non-standard function insts.  This will
> require searching up the call graph in some cases (e.g. you'll need to
> look at all callers of mode_is_fully_input and mode_is_fully_output).

done.

> 
> > +++ compiler/inst_util.m	2 Aug 2001 15:05:03 -0000
> > @@ -98,6 +98,25 @@
> >  	%       the same in both.
> >  
> >  %-----------------------------------------------------------------------------%
> > +
> > +	% Succeed iff the first argument is a function pred_inst_info
> > +	% with non-standard mode.
> > +
> > +:- pred pred_inst_info_is_nonstandard_func_mode(pred_inst_info, module_info).
> > +:- mode pred_inst_info_is_nonstandard_func_mode(in, in) is semidet.
> 
> s/with non-standard mode/whose mode does not match the standard func mode/
> 
> e.g. this predicate fails for "func(in) = uo", because that matches
> the standard func mode "func(in) = out", even though it isn't the same
> as the standard func mode.
> 
> (Might be worth adding the preceding sentence as a comment.)

done.

> 
> > +	% Succeed iff the first argument is a function ground_inst_info
> > +	% with non-standard mode.
> > +
> > +:- pred ground_inst_info_is_nonstandard_func_mode(ground_inst_info,
> > +			module_info).
> > +:- mode ground_inst_info_is_nonstandard_func_mode(in, in) is semidet.
> 
> Likewise.

done.

> 
> > +++ tests/hard_coded/ho_func_default_inst.m	3 Aug 2001 00:17:04 -0000
> > @@ -0,0 +1,43 @@
> > +% This test checks that a higher order func type with inst ground is 
> > +% able to be treated as a though it has the default function mode.
> 
> I think this change needs more test cases.
> The reasoning involved in handling some of the tricky cases is
> quite easy to get wrong, and so even if your change gets it
> right, it's important to have test cases in the test suite
> to make sure that future maintainers don't mess it up.
> 
> In particular, I think it's important to test matching
> of the following modes against `in':
> 
> 	- modes like `func(in) = uo)'
> 	- modes like `func(di) = uo)'
> 	- modes like `func(in) = out(non_empty_list)'
> 	- modes like `func(in(non_empty_list)) = out'
> 

done.

> 
> Apart from that, this diff looks fine.  Please post another diff
> (preferably relative) when you've addressed these comments.

Here it is.


Estimated hours taken: 8
Branches: main

Implement a change to the mode system suggested by Ralph Becket to make use of
higher order functions a bit easier.

During mode checking of higher order calls, if the variable being called has a
higher-order function type, but only a ground inst with no higher-order
information, assume that it has the default function modes.

Also, when doing anything that might cause a variable's inst to lose higher
order mode information, report a mode error if the variable has a non-standard
higher order function mode.  Situations where this may occur are at call sites,
exit sites and when merging insts at the end of a branched goal.

Note that because of this restriction, this change is not backwards compatible.

compiler/inst_util.m:
	Define some predicates to check for and produce pred_inst_infos for
	default function modes.
	In 'inst_merge', ensure that higher order inst information is not lost
	from non-standard function insts.

compiler/inst_match.m:
	In 'inst_matches_initial' and 'inst_matches_final', ensure that higher
	order inst information is not lost from non-standard function insts.
	Also allow 'inst_matches_{initial,final,binding}' to succeed
	where the first inst is a standard function inst and the
	second is ground.

compiler/modecheck_call.m:
	In 'modecheck_higher_order_call', if the variable to be called has no
	pred_inst_info, but the correct higher-order function type, assume it
	has the default function modes. 

tests/hard_coded/Mmakefile:
tests/hard_coded/ho_func_default_inst.m:
tests/hard_coded/ho_func_default_inst.exp:
tests/invalid/Mmakefile:
tests/invalid/ho_default_func_1.m:
tests/invalid/ho_default_func_1.err_exp:
tests/invalid/ho_default_func_2.m:
tests/invalid/ho_default_func_2.err_exp:
tests/invalid/ho_default_func_3.m:
tests/invalid/ho_default_func_3.err_exp:
	Add some test cases.

diff -u compiler/inst_match.m compiler/inst_match.m
--- compiler/inst_match.m
+++ compiler/inst_match.m
@@ -145,12 +145,18 @@
         % succeed if the inst is fully ground (i.e. contains only
         % `ground', `bound', and `not_reached' insts, with no `free'
         % or `any' insts).
+	% This predicate succeeds for non-standard function insts so some care
+	% needs to be taken since these inst may not be replaced by a less
+	% precise inst that uses the higher-order mode information.
 :- pred inst_is_ground(module_info, inst).
 :- mode inst_is_ground(in, in) is semidet.
 
         % succeed if the inst is not partly free (i.e. contains only
         % `any', `ground', `bound', and `not_reached' insts, with no
         % `free' insts).
+	% This predicate succeeds for non-standard function insts so some care
+	% needs to be taken since these inst may not be replaced by a less
+	% precise inst that uses the higher-order mode information.
 :- pred inst_is_ground_or_any(module_info, inst).
 :- mode inst_is_ground_or_any(in, in) is semidet.
 
diff -u compiler/inst_util.m compiler/inst_util.m
--- compiler/inst_util.m
+++ compiler/inst_util.m
@@ -99,24 +99,33 @@
 
 %-----------------------------------------------------------------------------%
 
-	% Succeed iff the first argument is a function pred_inst_info
-	% with non-standard mode.
+:- pred inst_contains_nonstandard_func_mode(inst, module_info).
+:- mode inst_contains_nonstandard_func_mode(in, in) is semidet.
+
+	% inst_contains_nonstandard_func_mode(Inst, ModuleInfo) succeeds iff the
+	% inst contains a higher-order function inst that does not match the
+	% standard function mode `(in, ..., in) = out is det'.
+	% E.g. this predicate fails for "func(in) = uo" because that matches the
+	% standard func mode "func(in) = out", even though it isn't the same as
+	% the standard func mode.
 
 :- pred pred_inst_info_is_nonstandard_func_mode(pred_inst_info, module_info).
 :- mode pred_inst_info_is_nonstandard_func_mode(in, in) is semidet.
 
-	% Succeed iff the first argument is a function ground_inst_info
-	% with non-standard mode.
+	% Succeed iff the first argument is a function pred_inst_info
+	% whose mode does not match the standard func mode.
 
 :- pred ground_inst_info_is_nonstandard_func_mode(ground_inst_info,
 			module_info).
 :- mode ground_inst_info_is_nonstandard_func_mode(in, in) is semidet.
 
-
-	% Return the standard mode for a function of the given arity.
+	% Succeed iff the first argument is a function ground_inst_info
+	% whose mode does not match the standard func mode.
 
 :- func pred_inst_info_standard_func_mode(arity) = pred_inst_info.
 
+	% Return the standard mode for a function of the given arity.
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -1633,11 +1642,37 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
+inst_contains_nonstandard_func_mode(Inst, ModuleInfo) :-
+	set__init(Expansions0),
+	inst_contains_nonstandard_func_mode_2(Inst, ModuleInfo, Expansions0).
+
+:- pred inst_contains_nonstandard_func_mode_2(inst, module_info, set(inst)).
+:- mode inst_contains_nonstandard_func_mode_2(in, in, in) is semidet.
+
+inst_contains_nonstandard_func_mode_2(ground(_, GroundInstInfo), ModuleInfo,
+		_Expansions) :-
+	ground_inst_info_is_nonstandard_func_mode(GroundInstInfo, ModuleInfo).
+inst_contains_nonstandard_func_mode_2(bound(_, BoundInsts), ModuleInfo,
+		Expansions) :-
+	list__member(functor(_, Insts), BoundInsts),
+	list__member(Inst, Insts),
+	inst_contains_nonstandard_func_mode_2(Inst, ModuleInfo, Expansions).
+inst_contains_nonstandard_func_mode_2(inst_var(_), _, _) :-
+	error("internal error: uninstantiated inst parameter").
+inst_contains_nonstandard_func_mode_2(Inst, ModuleInfo, Expansions0) :-
+	Inst = defined_inst(InstName),
+	\+ set__member(Inst, Expansions0),
+	set__insert(Expansions0, Inst, Expansions1),
+	inst_lookup(ModuleInfo, InstName, Inst2),
+	inst_contains_nonstandard_func_mode_2(Inst2, ModuleInfo, Expansions1).
+
+%-----------------------------------------------------------------------------%
+
 pred_inst_info_is_nonstandard_func_mode(PredInstInfo, ModuleInfo) :-
 	PredInstInfo = pred_inst_info(function, ArgModes, _),
 	Arity = list__length(ArgModes),
-	\+ pred_inst_matches(pred_inst_info_standard_func_mode(Arity),
-		PredInstInfo, ModuleInfo).
+	\+ pred_inst_matches(PredInstInfo,
+		pred_inst_info_standard_func_mode(Arity), ModuleInfo).
 
 ground_inst_info_is_nonstandard_func_mode(GroundInstInfo, ModuleInfo) :-
 	GroundInstInfo = higher_order(PredInstInfo),
diff -u tests/invalid/Mmakefile tests/invalid/Mmakefile
--- tests/invalid/Mmakefile
+++ tests/invalid/Mmakefile
@@ -47,6 +47,7 @@
 	func_errors.m \
 	funcs_as_preds.m \
 	ho_default_func_1.m \
+	ho_default_func_3.m \
 	ho_type_mode_bug.m \
 	ho_unique_error.m \
 	impure_method_impl.m \

-- 
David Overton      Department of Computer Science & Software Engineering
PhD Student        The University of Melbourne, Victoria 3010, Australia
+61 3 8344 9159    http://www.cs.mu.oz.au/~dmo
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list