[m-rev.] For review: State Variables

Simon Taylor stayl at cs.mu.OZ.AU
Wed May 15 05:43:41 AEST 2002


On 09-May-2002, Ralph Becket <rafe at cs.mu.OZ.AU> wrote:
> Simon Taylor, Monday,  6 May 2002:
> > On 02-May-2002, Ralph Becket <rafe at cs.mu.OZ.AU> wrote:
> > > +		% Handle !.X state variable references.
> > > +		{ F = term__atom("!.") },
> > > +		{ Args = [term__variable(StateVar)] }
> > > +	->
> > > +		dot(Context, StateVar, Var, VarSet0, VarSet,
> > > +			SInfo0, SInfo),
> > > +		{ Goal = svar_unification(Context, X, Var) },
> > > +		{ Info = Info0 }
> > > +	;
> > > +		% Handle !:X state variable references.
> > > +		{ F = term__atom("!:") },
> > > +		{ Args = [term__variable(StateVar)] }
> > > +	->
> > > +		colon(Context, StateVar, Var, VarSet0, VarSet,
> > > +			SInfo0, SInfo),
> > > +		{ Goal = svar_unification(Context, X, Var) },
> > > +		{ Info = Info0 }
> > 
> > The way you've done this the type and mode error messages for
> > state variable references will be really awful. 
> 
> Fixed.

Where are the test cases for the error messages?
 
> > > -get_conj(Goal, Subst, Conj0, VarSet0, Conj, VarSet, Info0, Info) -->
> > > +get_conj(Goal, Subst, Conj0, VarSet0, Conj, VarSet, Info0, Info,
> > > +		SInfo0, SInfo) -->
> > >  	(
> > >  		{ Goal = (A,B) - _Context }
> > >  	->
> > > -		get_conj(B, Subst, Conj0, VarSet0, Conj1, VarSet1,
> > > -						Info0, Info1),
> > > -		get_conj(A, Subst, Conj1, VarSet1, Conj, VarSet, Info1, Info)
> > > +		get_conj(A, Subst, Conj0, VarSet0, Conj1, VarSet1,
> > > +			Info0, Info1, SInfo0, SInfo1),
> > > +		get_conj(B, Subst, Conj1, VarSet1, Conj, VarSet,
> > > +			Info1, Info,  SInfo1, SInfo)
> > >  	;
> > >  		transform_goal(Goal, VarSet0, Subst, Goal1, VarSet,
> > > -						Info0, Info),
> > > +			Info0, Info,  SInfo0, SInfo),
> > >  		{ goal_to_conj_list(Goal1, ConjList) },
> > >  		{ list__append(ConjList, Conj0, Conj) }
> > >  	).
> > 
> > You're now building Conj in reverse, so ConjList needs to be reversed
> > before adding it to Conj0 (same for get_par_conj and get_disj).
> 
> The lists are reversed in the respective callers.

Conj0 and Conj are reversed, ConjList isn't. I'd suggest s/Conj/RevConj/
to avoid confusion (and in get_par_conj and get_disj).
 
> > > +finish_if_then_else(Context, Then0, Then, Else0, Else, VarSet0, VarSet,
> > > +		SInfoT, SInfoE, SInfo) :-
> > > +	SInfo0       = SInfoT,
> > > +	N            = int__max(SInfoT ^ num, SInfoE ^ num),
> > > +	next_svar_info(N, VarSet0, VarSet, SInfo0, SInfo),
> > > +
> > > +	goal_info_init(Context, GoalInfo),
> > > +
> > > +	goal_to_conj_list(Then0, ThenGoals0),
> > > +	ThenUnifiers = svar_unifiers(Context, SInfo ^ dot, SInfoT ^ dot),
> > > +	conj_list_to_goal(ThenGoals0 ++ ThenUnifiers, GoalInfo, Then),
> > > +
> > > +	goal_to_conj_list(Else0, ElseGoals0),
> > > +	ElseUnifiers = svar_unifiers(Context, SInfo ^ dot, SInfoE ^ dot),
> > > +	conj_list_to_goal(ElseGoals0 ++ ElseUnifiers, GoalInfo, Else).
> > 
> > This doesn't handle code like the following properly:
> > 
> > 	( p(!X) ->
> > 		q
> > 	;
> > 		r(!X)
> > 	).
> 
> Fixed.

I'm not totally convinced. You should document somewhere
how this case is handled. There should also be a test case.
 
> --- make_hlds.m	2 May 2002 03:54:54 -0000
> +++ make_hlds.m	9 May 2002 08:26:46 -0000
> @@ -3991,31 +4007,43 @@
>  		ModuleInfo - QualInfo - ClausesInfo) -->
>  	(
>  		{ InstanceClause = clause(CVarSet, PredOrFunc, PredName,
> -				HeadTerms, Body) }
> +				HeadTerms0, Body) }

You should add a test for state variables in instance clauses.

> +:- pred report_svar_unify_error(prog_context, prog_varset, svar, io, io).
> +:- mode report_svar_unify_error(in, in, in, di, uo) is det.
> +
> +report_svar_unify_error(Context, VarSet, StateVar) -->
> +		{ Name = varset__lookup_name(VarSet, StateVar) },
> +		prog_out__write_context(Context),
> +		report_warning(string__format("\
> +Error: !%s cannot appear as a unification argument.\n", [s(Name)])),
> +		globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
> +		(
> +			{ VerboseErrors = yes },
> +			prog_out__write_context(Context),
> +			report_warning(string__format("\
> +       You probably meant !.%s or !:%s.\n", [s(Name), s(Name)]))
> +		;
> +			{ VerboseErrors = no }
> +		).

The `--verbose-errors' part is short enough that you could just
always include it in the message.

> @@ -7614,7 +7689,7 @@
>  :- mode build_lambda_expression(in, in, in, in, in, in, in, in,
>  		in, in, in, out, out, in, out, in, di, uo) is det.
>  
> -build_lambda_expression(X, PredOrFunc, EvalMethod, Args, Modes, Det,
> +build_lambda_expression(X, PredOrFunc, EvalMethod, Args0, Modes, Det,
>  		ParsedGoal, VarSet0, Context, MainContext, SubContext,
>  		Goal, VarSet, Info1, Info, SInfo0) -->
>  	%
> @@ -7652,56 +7727,75 @@
>  	% corresponding to the function result term is a new variable,
>  	% to avoid the function result term becoming lambda-quantified.
>  	%
> -	{ list__length(Args, NumArgs) },
> -	{ varset__new_vars(VarSet0, NumArgs, LambdaVars, VarSet1) },
> -	{ map__init(Substitution) },
> -	{ prepare_for_head(SInfo0, SInfo1) },
> -	{ hlds_goal__true_goal(Head0) },
> -	{ ArgContext = head(PredOrFunc, NumArgs) },
> +	(
> +		{ illegal_state_var_func_result(PredOrFunc, Args0, StateVar) }
> +	->
> +		report_illegal_func_svar_result(Context, VarSet0, StateVar),
> +		{ true_goal(Goal) },
> +		{ VarSet = VarSet0 },
> +		{ Info   = Info1 }
> +	;
> +		{ prepare_for_lambda(SInfo0, SInfo1) },
> +		{ Args1  = expand_bang_state_var_args(Args0) },

That's not right. The following example should be an error.
	(pred(!X::in, !:X::out) is det :- ...) 

> +:- func reconciled_disj_svar_info(prog_varset, hlds_goal_svar_infos) =
> +		svar_info.

This whole section needs more documentation.

> +:- pred substitute_state_var_mappings(list(prog_term), list(prog_term),
> +		prog_varset, prog_varset, svar_info, svar_info, io, io).
> +:- mode substitute_state_var_mappings(in, out, in, out, in, out, di, uo) is det.

Documentation.

> +:- pred report_illegal_func_svar_result(prog_context, prog_varset, svar,
> +		io, io).
> +:- mode report_illegal_func_svar_result(in, in, in, di, uo) is det.
> +
> +report_illegal_func_svar_result(Context, VarSet, StateVar) -->
> +	{ Name = varset__lookup_name(VarSet, StateVar) },
> +	prog_out__write_context(Context),
> +	report_warning(string__format("\
> +Warning: !%s cannot be a function result.\n", [s(Name)])),
> +	globals__io_lookup_bool_option(verbose_errors, Verbose),
> +	(
> +		{ Verbose = yes },
> +		prog_out__write_context(Context),
> +		report_warning(string__format("\
> +         You probably meant !.%s or !:%s.\n", [s(Name), s(Name)]))
> +	;
> +		{ Verbose = no }

The `--verbose-errors' part can just go in with the rest.

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