[m-dev.] for review: constrain interface assertions to using interface symbols

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Nov 11 14:37:09 AEDT 1999


On 11-Nov-1999, Peter Ross <petdr at cs.mu.OZ.AU> wrote:
> Assertion declarations in the interface must not contain any symbols from
> modules imported only in the implementation.  This constraint requires
> that each imported symbol be annotated with whether it is imported from
> the interface or implementation.
>
> compiler/prog_data.m:
>     Update the pseudo declaration `:- imported' to include which section
>     (either implementation or interface) the items following it where
>     imported from.

s/where/were/

> compiler/module_qual.m:
>     Any unqualified symbol in an assertion might come from *any*
>     of the imported modules, so turn off the warning about modules which
>     are imported in the interface but not used.

I suggest you make it clear in the log message exactly when
you are disabling the warning:
	- if an unqualified symbol appears in an assertion?
	- if the interface contains an assertion?
	- all the time?

> compiler/accumulator.m:
>     Use where a symbol is imported from when deciding whether an
>     assertion in the interface is valid.

Did you mean `assertion.m' rather than `accumulator.m' here?
I don't see why accumulator.m should have to change as a result
of this change.

> Index: hlds_pred.m
> ===================================================================
> RCS file: /home/staff/zs/imp/mercury/compiler/hlds_pred.m,v
> retrieving revision 1.66
> diff -u -r1.66 hlds_pred.m
> --- hlds_pred.m	1999/10/15 03:44:49	1.66
> +++ hlds_pred.m	1999/10/27 04:48:20
> @@ -974,8 +975,8 @@
>  pred_info_mark_as_external(PredInfo0, PredInfo) :-
>  	PredInfo0 = predicate(A, B, C, D, E, F, G, H, I, _, K, L, M, N, O, P,
>  		Q, R, S, T, U, V),
> -	PredInfo  = predicate(A, B, C, D, E, F, G, H, I, imported, K, L, M, 
> -		N, O, P, Q, R, S, T, U, V).
> +	PredInfo  = predicate(A, B, C, D, E, F, G, H, I, imported(interface),
> +		K, L, M, N, O, P, Q, R, S, T, U, V).

Hmm, is that correct?
Shouldn't you check whether the old status was
`local' or `exported'?  If it was `local', then
the new status should be `imported(implementation)',
not `imported(interface)'.

I suggest you add the following test case to tests/invalid

	% this is invalid because the interface refers
	% to stuff defined only in the implementation
	:- module tricky_assert1.
	:- interface.
	:- assertion tricky_assert1__local.

	:- implementation.
	:- pred tricky_assert1__local is semidet.
	:- external(tricky_assert1__local/0).

and the following one to tests/valid:

	:- module tricky_assert2.
	:- interface.
	:- pred tricky_assert2__local is semidet.
	:- assertion tricky_assert2__local.

	:- implementation.
	:- external(tricky_assert2__local/0).

The current compiler correctly rejects tricky_assert1 but incorrectly
also rejects tricky_assert2.  I think with your changes as posted, the
compiler will correctly accept tricky_assert2 but will incorrectly also
accept tricky_assert1.

> +collect_mq_info_2(assertion(_, _), Info0, Info) :-
> +	% Any unqualified symbol in the assertion might come from *any*
> +	% of the imported modules.
> +	% There's no way for us to tell which ones.
> +	% So we conservatively assume that it uses all of them.
> +	% XXX a better solution would be to only make this assumption if
> +	% the assertion contains an unqualified symbol, however since
> +	% the structure isn't in superhomogenous form yet processing the
> +	% goal is complicated.
> +	set__init(UnusedInterfaceModules),
> +	mq_info_set_unused_interface_modules(Info0, UnusedInterfaceModules,
> +		Info).

Well, not _that_ complicated; you do have to traverse the `goal' type
(requiring one ~30-line predicate), but once you get to a `call'
or `unify', it's fairly easy: 

	:- pred goal_contains_unqual_sym(goal::in) is semidet.
	... lots of clauses with recursive calls, then ...
	goal_contains_unqual_sym(call(SymName, Args)) :-
		sym_name_and_args_contains_unqual_sym(SymName, Args).
	goal_contains_unqual_sym(unify(LHS, RHS)) :-
		( term_contains_unqual_sym(LHS)
		; term_contains_unqual_sym(LHS)
		).

	term_contains_unqual_sym(Term) :-
		sym_name_and_args(Term, SymName, Args),
		sym_name_and_args_contains_unqual_sym(SymName, Args).

	sym_name_and_args_contains_unqual_sym(SymName, Args) :-
		(
			SymName = unqualified(_)
		;
			list__member(Arg, Args),
			term_contains_unqual_sym(Arg)
		).

Go on, it should only take you another 5-15 minutes to finish that off ;-)

>  :- pred warn_if_duplicate_use_import_decls(module_name, list(module_name),
>  		list(module_name), list(module_name), list(module_name), 
> +		list(module_name), list(module_name), list(module_name), 
> +		list(module_name), io__state, io__state).
> +:- mode warn_if_duplicate_use_import_decls(in, in, out, in, out, in, out,
> +		in, out, di, uo) is det.
> +
> +% This predicate ensures that all every import_module declaration is
> +% checked against every use_module declaration.
> +% warn_if_duplicate_use_import_decls/7 is called to generate the actual
> +% warnings.
> +
> +warn_if_duplicate_use_import_decls(ModuleName,
> +		IntImportedModules0, IntImportedModules, 
> +		IntUsedModules0, IntUsedModules, 
> +		ImpImportedModules0, ImpImportedModules, 
> +		ImpUsedModules0, ImpUsedModules) -->
> +
> +	warn_if_duplicate_use_import_decls(ModuleName,
> +		IntImportedModules0, IntImportedModules1,
> +		IntUsedModules0, IntUsedModules1),
> +	warn_if_duplicate_use_import_decls(ModuleName,
> +		IntImportedModules1, IntImportedModules,
> +		ImpUsedModules0, ImpUsedModules1),
> +
> +	warn_if_duplicate_use_import_decls(ModuleName,
> +		ImpImportedModules0, ImpImportedModules1,
> +		IntUsedModules1, IntUsedModules),
> +	warn_if_duplicate_use_import_decls(ModuleName,
> +		ImpImportedModules1, ImpImportedModules,
> +		ImpUsedModules1, ImpUsedModules).
> +

Actually I think it makes perfect sense to have `:- use_module foo'.
in the interface and `:- import_module foo.' in the implementation.
The other three cases don't make sense, but that one does.
The compiler should not warn about it.
So I think you should delete that third call to
`warn_if_duplicate_use_import_decls',
and modify the documentation for this pred accordingly.

Apart from that, this change looks good, but I'd like to see another
round of reviewing for it.

Cheers,
	Fergus.

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