[m-rev.] For review: (no attachments) Extensions to constraints based mode analysis.

Ralph Becket rafe at cs.mu.OZ.AU
Wed Feb 1 19:38:14 AEDT 2006


Throughout you use `ie' instead of `i.e.,'.  If you want full points
for style, you only use `i.e.,' in parentheses, otherwise write out
`that is' (or `id est' if you're a classical buff).

> Index: compiler/abstract_mode_constraints.m
> ===================================================================
> +%-----------------------------------------------------------------------------%
> +
> +    % equiv_no(Context, MCVar, !Constraints) constrains MCVar to `no' in
> +    % Constraints. Context should be the context of the goal or
> +    % declaration that imposed this constraint.
> +    %
> +:- pred equiv_no(prog_context::in, mc_var::in, pred_p_c_constraints::in,
> +    pred_p_c_constraints::out) is det.

Why just `equiv_no' and not `equiv_yes'?  Why not make the no/yes
binding a parameter?

> +    % xor(Context, A, B, !Constraints) constrains mode constraint variables A
> +    % and B in Constraints by the constraint (A xor B), ie constrains exactly
> +    % one of them to be true. Context should be the context of the goal or
> +    % declaration that imposed this constraint.
> +    %
> +:- pred xor(prog_context::in, mc_var::in, mc_var::in, pred_p_c_constraints::in,
> +    pred_p_c_constraints::out) is det.

I don't think `xor' is a good name, but I can't think of anything better
off hand.

> 
>  %-----------------------------------------------------------------------------%
>  %-----------------------------------------------------------------------------%
> 
>  :- implementation.
> 
> +:- import_module parse_tree.error_util.
> +
> +:- import_module int.
>  :- import_module string.
> 
>  %-----------------------------------------------------------------------------%
> 
> +    % `unit'-like type used to distinguish mode constraint variables.
> +    %
>  :- type mc_type ---> mc_type.

This is usually referred to as a "dummy type".

> +abstract_mode_constraints.add_constraint(Context,
> +    ConstraintFormula, !PredConstraints) :-

There should be an extra level of indentation on the line above.

> +    AllProcsConstraints = !.PredConstraints ^ pred_constraints,
> +    ConstraintAnnotation = constraint_annotation(Context),
> +    FormulaAndAnnotation = pair(ConstraintFormula, ConstraintAnnotation),
> +    !:PredConstraints = !.PredConstraints ^ pred_constraints :=
> +        list.cons(FormulaAndAnnotation, AllProcsConstraints).

Why `list.cons(...)' rather than just
`[FormulaAndAnnotation | AllProcsConstraints]'?

> +    % Prints the variable bindings of this solution, one per line.
> +    %
> +:- pred pretty_print_bindings(mc_varset::in, mc_bindings::in,
> int::in, int::out,
> +    io::di, io::uo) is det.
> +
> +pretty_print_bindings(VarSet, Bindings, N, N + 1, !IO) :-
> +    io.write_string("Solution " ++ string.from_int(N) ++ ":\n{\n", !IO),
> +    Variables = map.keys(Bindings),
> +    list.foldl((pred(Var::in, IO0::di, IO::uo) is det :-
> +            io.write_string("    ", IO0, IO1),
> +            io.write_string(varset.lookup_name(VarSet, Var), IO1, IO2),
> +            io.write_string(" = ", IO2, IO3),
> +            map.lookup(Bindings, Var, Value),
> +            io.print(Value, IO3, IO4),
> +            io.nl(IO4, IO)
> +        ),
> +        Variables, !IO),
> +    io.write_string("}\n", !IO).

That would be clearer if the lambda was replaced by a named predicate.

> Index: compiler/build_mode_constraints.m
> ===================================================================
> @@ -72,99 +80,114 @@
> 
>      % An abstract representation of a mode constraint variable.
>      %
> -    % It represents the constraint variable that determines whether
> -    % the program variable specified is produced at the goal path
> -    % specified.
> +    % ProgVar `in` PredId, `at` GoalPath represents the constraint
> +    % variable of the proposition that ProgVar is produced at
> +    % goal GoalPath in predicate PredId.

Do you mean to include that comma before `at`?

>      % mode_decls_constraints(ModuleInfo, VarMap, PredId, Decls,
> -    % HeadVarsList, Constraints)
> +    %   HeadVarsList, Constraints)
>      %
>      % Constraints is the disjunction of the constraints for
>      % individual declared modes being satisfied.  ie
>      % disj([ConstraintsForMode1, ..., ConstraintsForModen])
>      %
> -    % Note that if Decls is an empty list, this is interpreted as
> -    % there being no modes for which the predicate can be executed
> -    % and the returned constraints are [disj([])] which cannot be
> -    % satisfied. Mode declarations for predicates with no declared
> -    % modes should not be handled by this - they must be handled
> -    % elsewhere.
> -    %
>      % The constraints for a predicate with declared modes is the

Do you mean for a predicate or for a call?

>      % disjunction of the constraints for each declared mode. If,
>      % according to the mode declaration, a variable is not initially



> +add_goal_constraints(ModuleInfo, ProgVarset, PredId, GoalExpr - GoalInfo,
> +        !VarInfo, !Constraints) :-
>      goal_info_get_nonlocals(GoalInfo, Nonlocals),
>      goal_info_get_goal_path(GoalInfo, GoalPath),
> +    goal_info_get_context(GoalInfo, Context),
> +    add_goal_expr_constraints(ModuleInfo, ProgVarset, PredId,
> GoalExpr, Context,

Is this an indentation error?

> +add_goal_expr_constraints(ModuleInfo, ProgVarset, CallerPredId, GoalExpr,
> +        Context, GoalPath, _Nonlocals, !VarInfo, !Constraints) :-
> +    GoalExpr = call(CalleePredId, _, Args, _, _, _),
> +    module_info_pred_info(ModuleInfo, CalleePredId, CalleePredInfo),
> +
> +    ( pred_info_infer_modes(CalleePredInfo) ->
> +        % No modes declared so just constrain the hearvars

s/hearvars/headvars/

> +    % A variable bound at any disjunct is bound for the disjunction
> +    % as a whole. If a variable can be bound at one disjunct
> +    % it must be able to be bound at any.

Grammar correction:

% A variable bound by any disjunct is bound by the disjunction
% as a whole. If a variable is bound by one disjunct then
% it must be bound by all of them.

> Index: compiler/check_hlds.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/check_hlds.m,v
> retrieving revision 1.10
> diff -u -r1.10 check_hlds.m
> --- compiler/check_hlds.m	12 Oct 2005 23:51:34 -0000	1.10
> +++ compiler/check_hlds.m	25 Jan 2006 04:41:54 -0000
> @@ -38,8 +38,6 @@
> 
>  % Mode analysis
>  %:- module mode_analysis.
> -   :- include_module abstract_mode_constraints.
> -   :- include_module build_mode_constraints.
>     :- include_module delay_info.
>     :- include_module inst_match.
>     :- include_module inst_util.
> @@ -53,9 +51,18 @@
>     :- include_module modecheck_call.
>     :- include_module modecheck_unify.
>     :- include_module modes.
> -   :- include_module prop_mode_constraints.
>     :- include_module unify_proc.
>     :- include_module unique_modes.
> +
> +   % XXX This doesn't belong here but we don't know where it's home is at
> +   % the moment.
> +   %
> +   :- include_module abstract_mode_constraints.
> +   :- include_module build_mode_constraints.
> +   :- include_module mcsolver.
> +   :- include_module ordering_mode_constraints.
> +   :- include_module prop_mode_constraints.

I think these do belong here: modes.m is a submodule of check_hlds.

> Index: compiler/ordering_mode_constraints.m (new file)
> ===================================================================
> 
>     % add_ordering_constraint(Constraint, !OCI) adds Constraint
>     % to the ordering constraints store. It fails if it immediately
>     % detects a contradiction (at the moment, this means it has
>     % detected a loop in the producer/consumer dependency graph).
>     %
> :- pred add_ordering_constraint(mode_ordering_constraint::in,
>     ordering_constraints_info::in, ordering_constraints_info::out) is semidet.
> 
>     % add_lt_constraint(A, B, !OCI) constrains conjunct A to come
>     % before conjunct B, in the constraints store.
>     %
> :- pred add_lt_constraint(conjunct_id::in, conjunct_id::in,
>     ordering_constraints_info::in, ordering_constraints_info::out) is semidet.

Why do we need both of these predicates?

> mode_reordering(PredConstraintsMap, VarMap, SCCs, !ModuleInfo) :-
>     (
>         list.foldl(scc_reordering(PredConstraintsMap, VarMap), SCCs,
>             !ModuleInfo)
>     ->
>         true
>     ;
>         % XXX Until mode inference is complete and the final
>         % structure of this module is decided this is all that
>         % can be done.
>         sorry(this_file, "mode ordering failure")
>     ).

Hmm.  Do you have to bail out?  Can't you mark the pred. as "to be
handled by the old mode ordering mechanism"?  This situation occurs
frequently in your diff.

> %-----------------------------------------------------------------------------%
> 
>     % add_ordering_constraint(Constraint, OCI0, OCI) adds Constraint
>     % to the ordering constraints store. It fails if it immediately
>     % detects a contradiction (at the moment, this means it has
>     % detected a loop in the producer consumer dependency graph - eg

s/eg/e.g.,/ - as with `i.e.,'.

>     % prog_var_ordering_constraints(VarMap, Bindings, ProgVar, RepVars,
>     %   !OCInfo)
>     %
>     % Adds ordering constraints for a conjunction to OCInfo.
>     % Specifically, those relating to which conjuncts produce and which
>     % consume the variable ProgVar. See conjunct_ordering_constraints
>     % for details.
>     %
> :- pred prog_var_ordering_constraints(mc_var_map::in, mc_bindings::in,
>     prog_var::in, list(mc_rep_var)::in,
>     ordering_constraints_info::in, ordering_constraints_info::out) is semidet.

What about impurity related ordering constraints?

>     % original_order_constraints(N, MOCs) produces a list of constraints MOCs
>     % that describe a complete order for N conjuncts, such that they are not
>     % reordered at all from their original positions.
>     %
> :- pred original_order_constraints(int::in,
>     mode_ordering_constraints::out) is det.
> 
> original_order_constraints(N, MOCs) :-
>     complete_order_constraints(1 `..` N, MOCs).

Since (..) is already an infix operator, you don't need the backquotes.

>     % add_complete_order_constraints(Xs, !MOCs) adds a list of constraints
>     % that describe a compete order for Xs such that it is not reordered
>     % at all.
>     %
> :- pred add_complete_order_constraints(list(conjunct_id)::in,
>     set(mode_ordering_constraint)::in,
>     set(mode_ordering_constraint)::out) is det.
> 
> add_complete_order_constraints([], !MOCs).
> add_complete_order_constraints([Conjunct | Conjuncts], !MOCs) :-
>     list.foldl(insert_lt_constraint(Conjunct), Conjuncts, !MOCs),
>     add_complete_order_constraints(Conjuncts, !MOCs).

Do you need all O(n^2) ordering constraints?  Can't you do it with O(n)?

>     % constraint_if_possible(Constraints, !OCI)

s/constraint_if_possible/constrain_if_possible/

> Index: compiler/mcsolver.m (new file)
> ===================================================================

>     % For debugging purposes only.
> % :- pred main(io :: di, io :: uo) is det.

Do you still want this here?

Otherwise that's fine and you should check it in!

Cheers,
-- Ralph
--------------------------------------------------------------------------
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