[m-rev.] diff: headvar_names.m
Zoltan Somogyi
zs at csse.unimelb.edu.au
Mon May 14 20:57:57 AEST 2007
compiler/headvar_names.m:
compiler/typecheck.m:
Move the part of typecheck.m that deals with improving headvar names
into a module of its own.
There are no algorithmic changes.
compiler/hlds.m:
Include the new module.
compiler/notes/compiler_design.html:
Mention the new module.
Zoltan.
cvs diff: Diffing .
Index: headvar_names.m
===================================================================
RCS file: headvar_names.m
diff -N headvar_names.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ headvar_names.m 14 May 2007 10:39:50 -0000
@@ -0,0 +1,362 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2007 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: headvar_names.m.
+% Main author: fjh.
+%
+% This file contains code for improving the names of head variables.
+
+:- module hlds.headvar_names.
+
+:- interface.
+
+:- import_module hlds.hlds_pred.
+:- import_module libs.globals.
+
+ % If all clauses give a given head variables the same name, use this name
+ % instead of the introduced `HeadVar__n' names for the head variables
+ % in the pred_info. This gives better error messages, more meaningful
+ % variable names in the debugger and slightly faster compilation.
+ %
+:- pred maybe_improve_headvar_names(globals::in, pred_info::in, pred_info::out)
+ is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module hlds.hlds_args.
+:- import_module hlds.hlds_clauses.
+:- import_module hlds.hlds_goal.
+:- import_module hlds.goal_util.
+:- import_module libs.compiler_util.
+:- import_module libs.options.
+:- import_module parse_tree.prog_data.
+
+:- import_module bool.
+:- import_module list.
+:- import_module map.
+:- import_module maybe.
+:- import_module set.
+:- import_module varset.
+:- import_module svmap.
+:- import_module svset.
+:- import_module svvarset.
+
+maybe_improve_headvar_names(Globals, !PredInfo) :-
+ pred_info_clauses_info(!.PredInfo, ClausesInfo0),
+ clauses_info_clauses_only(ClausesInfo0, Clauses0),
+ clauses_info_get_headvars(ClausesInfo0, HeadVars0),
+ clauses_info_get_varset(ClausesInfo0, VarSet0),
+ (
+ % Don't do this when making a `.opt' file.
+ % intermod.m needs to perform a similar transformation
+ % which this transformation would interfere with (intermod.m
+ % places the original argument terms, not just the argument
+ % variables in the clause head, and this pass would make it
+ % difficult to work out what were the original arguments).
+ globals.lookup_bool_option(Globals, make_optimization_interface, yes)
+ ->
+ true
+ ;
+ Clauses0 = [SingleClause0]
+ ->
+ SingleClause0 = clause(ApplicableProcs, Goal0, Language, Context),
+
+ Goal0 = hlds_goal(_, GoalInfo0),
+ goal_to_conj_list(Goal0, Conj0),
+ improve_single_clause_headvars(Conj0, HeadVars0, [],
+ VarSet0, VarSet, map.init, Subst, [], RevConj),
+
+ goal_info_get_nonlocals(GoalInfo0, NonLocals0),
+ goal_util.rename_vars_in_var_set(no, Subst, NonLocals0, NonLocals),
+ goal_info_set_nonlocals(NonLocals, GoalInfo0, GoalInfo),
+ conj_list_to_goal(list.reverse(RevConj), GoalInfo, Goal),
+
+ apply_renaming_to_proc_arg_vector(Subst, HeadVars0, HeadVars),
+ clauses_info_set_headvars(HeadVars, ClausesInfo0, ClausesInfo1),
+
+ SingleClause = clause(ApplicableProcs, Goal, Language, Context),
+ clauses_info_set_clauses([SingleClause], ClausesInfo1, ClausesInfo2),
+ clauses_info_set_varset(VarSet, ClausesInfo2, ClausesInfo),
+ pred_info_set_clauses_info(ClausesInfo, !PredInfo)
+ ;
+ % If a headvar is assigned to a variable with the same name
+ % (or no name) in every clause, rename it to have that name.
+ list.map2(find_headvar_names_in_clause(VarSet0, HeadVars0), Clauses0,
+ VarNameInfoMaps, VarsInMapSets),
+ ConsensusMap = find_consensus_headvar_names(VarsInMapSets,
+ VarNameInfoMaps),
+ map.foldl(svvarset.name_var, ConsensusMap, VarSet0, VarSet),
+ clauses_info_set_varset(VarSet, ClausesInfo0, ClausesInfo),
+ pred_info_set_clauses_info(ClausesInfo, !PredInfo)
+ ).
+
+:- pred improve_single_clause_headvars(list(hlds_goal)::in,
+ proc_arg_vector(prog_var)::in, list(prog_var)::in,
+ prog_varset::in, prog_varset::out,
+ map(prog_var, prog_var)::in, map(prog_var, prog_var)::out,
+ list(hlds_goal)::in, list(hlds_goal)::out) is det.
+
+improve_single_clause_headvars([], _, _, !VarSet, !Subst, !RevConj).
+improve_single_clause_headvars([Goal | Conj0], HeadVars, SeenVars0,
+ !VarSet, !Subst, !RevConj) :-
+ ( goal_is_headvar_unification(HeadVars, Goal, HeadVar, yes(OtherVar)) ->
+ % If the headvar doesn't appear elsewhere the unification
+ % can be removed.
+ (
+ % The headvars must be distinct variables, so check that this
+ % variable doesn't already appear in the argument list.
+ \+ proc_arg_vector_member(HeadVars, OtherVar),
+ \+ list.member(OtherVar, SeenVars0),
+
+ \+ ( some [OtherGoal] (
+ ( list.member(OtherGoal, Conj0)
+ ; list.member(OtherGoal, !.RevConj)
+ ),
+ OtherGoal = hlds_goal(_, OtherGoalInfo),
+ goal_info_get_nonlocals(OtherGoalInfo, OtherNonLocals),
+ set.member(HeadVar, OtherNonLocals)
+ ))
+ ->
+ SeenVars = [OtherVar | SeenVars0],
+ svmap.det_insert(HeadVar, OtherVar, !Subst),
+
+ % If the variable wasn't named, use the `HeadVar__n' name.
+ (
+ \+ varset.search_name(!.VarSet, OtherVar, _),
+ varset.search_name(!.VarSet, HeadVar, HeadVarName)
+ ->
+ svvarset.name_var(OtherVar, HeadVarName, !VarSet)
+ ;
+ true
+ )
+ ;
+ !:RevConj = [Goal | !.RevConj],
+ SeenVars = SeenVars0,
+ ( varset.search_name(!.VarSet, OtherVar, OtherVarName) ->
+ % The unification can't be eliminated,
+ % so just rename the head variable.
+ svvarset.name_var(HeadVar, OtherVarName, !VarSet)
+ ; varset.search_name(!.VarSet, HeadVar, HeadVarName) ->
+ % If the variable wasn't named, use the `HeadVar__n' name.
+ svvarset.name_var(OtherVar, HeadVarName, !VarSet)
+ ;
+ true
+ )
+ )
+ ;
+ !:RevConj = [Goal | !.RevConj],
+ SeenVars = SeenVars0
+ ),
+ improve_single_clause_headvars(Conj0, HeadVars, SeenVars, !VarSet,
+ !Subst, !RevConj).
+
+:- type var_name_info_map == map(prog_var, var_name_info).
+:- type var_name_info
+ ---> var_name_info(
+ % Is the head variable unified with a functor?
+ vni_unified_with_functor :: bool,
+
+ % What are the names of the named variables it is unified with?
+ vni_unified_with_vars :: set(string)
+ ).
+
+ % Head variables that have the same name in each clause
+ % will have an entry of `yes(Name)' in the result map.
+ %
+:- pred find_headvar_names_in_clause(prog_varset::in,
+ proc_arg_vector(prog_var)::in, clause::in,
+ var_name_info_map::out, set(prog_var)::out) is det.
+
+find_headvar_names_in_clause(VarSet, HeadVars, Clause, VarNameInfoMap,
+ VarsInMap) :-
+ Goal = Clause ^ clause_body,
+ goal_to_conj_list(Goal, Conj),
+ list.foldl2(find_headvar_names_in_goal(VarSet, HeadVars), Conj,
+ map.init, VarNameInfoMap, set.init, VarsInMap).
+
+:- pred find_headvar_names_in_goal(prog_varset::in,
+ proc_arg_vector(prog_var)::in, hlds_goal::in,
+ var_name_info_map::in, var_name_info_map::out,
+ set(prog_var)::in, set(prog_var)::out) is det.
+
+find_headvar_names_in_goal(VarSet, HeadVars, Goal, !VarNameInfoMap,
+ !VarsInMap) :-
+ ( goal_is_headvar_unification(HeadVars, Goal, HeadVar, MaybeOtherVar) ->
+ svset.insert(HeadVar, !VarsInMap),
+ (
+ MaybeOtherVar = no,
+ ( map.search(!.VarNameInfoMap, HeadVar, VarNameInfo0) ->
+ VarNameInfo0 = var_name_info(_UnifiedFunctor, VarNames),
+ VarNameInfo = var_name_info(yes, VarNames),
+ svmap.det_update(HeadVar, VarNameInfo, !VarNameInfoMap)
+ ;
+ VarNameInfo = var_name_info(yes, set.init),
+ svmap.det_insert(HeadVar, VarNameInfo, !VarNameInfoMap)
+ )
+ ;
+ MaybeOtherVar = yes(OtherVar),
+ ( varset.search_name(VarSet, OtherVar, OtherVarName) ->
+ ( map.search(!.VarNameInfoMap, HeadVar, VarNameInfo0) ->
+ VarNameInfo0 = var_name_info(UnifiedFunctor, VarNames0),
+ set.insert(VarNames0, OtherVarName, VarNames),
+ VarNameInfo = var_name_info(UnifiedFunctor, VarNames),
+ svmap.det_update(HeadVar, VarNameInfo, !VarNameInfoMap)
+ ;
+ VarNames = set.make_singleton_set(OtherVarName),
+ VarNameInfo = var_name_info(no, VarNames),
+ svmap.det_insert(HeadVar, VarNameInfo, !VarNameInfoMap)
+ )
+ ;
+ true
+ )
+ )
+ ;
+ true
+ ).
+
+:- pred goal_is_headvar_unification(proc_arg_vector(prog_var)::in,
+ hlds_goal::in, prog_var::out, maybe(prog_var)::out) is semidet.
+
+goal_is_headvar_unification(HeadVars, Goal, HeadVar, MaybeOtherVar) :-
+ Goal = hlds_goal(GoalExpr, _),
+ GoalExpr = unify(LVar, RHS, _, _, _),
+ (
+ RHS = rhs_var(RVar),
+ ( proc_arg_vector_member(HeadVars, LVar) ->
+ HeadVar = LVar,
+ MaybeOtherVar = yes(RVar)
+ ; proc_arg_vector_member(HeadVars, RVar) ->
+ HeadVar = RVar,
+ MaybeOtherVar = yes(LVar)
+ ;
+ fail
+ )
+ ;
+ RHS = rhs_functor(_, _, _),
+ ( proc_arg_vector_member(HeadVars, LVar) ->
+ HeadVar = LVar,
+ MaybeOtherVar = no
+ ;
+ fail
+ )
+ ).
+
+:- func find_consensus_headvar_names(list(set(prog_var)),
+ list(var_name_info_map)) = map(prog_var, string).
+
+find_consensus_headvar_names(VarsInMapSets, VarNameInfoMaps) = ConsensusMap :-
+ VarsInMapSet = set.union_list(VarsInMapSets),
+ set.to_sorted_list(VarsInMapSet, VarsInMaps),
+ list.foldl(update_consensus_map_for_headvar(VarNameInfoMaps), VarsInMaps,
+ map.init, ConsensusMap).
+
+:- pred update_consensus_map_for_headvar(list(var_name_info_map)::in,
+ prog_var::in,
+ map(prog_var, string)::in, map(prog_var, string)::out) is det.
+
+update_consensus_map_for_headvar(VarNameInfos, HeadVar, !ConsensusMap) :-
+ MaybeName = find_consensus_name_for_headvar(VarNameInfos, HeadVar),
+ (
+ MaybeName = no
+ ;
+ MaybeName = yes(Name),
+ svmap.det_insert(HeadVar, Name, !ConsensusMap)
+ ).
+
+:- func find_consensus_name_for_headvar(list(var_name_info_map), prog_var)
+ = maybe(string).
+
+find_consensus_name_for_headvar(VarNameInfoMaps, HeadVar)
+ = MaybeConsensusName :-
+ group_var_infos(VarNameInfoMaps, HeadVar,
+ [], Inconsistents, [], Consistents, [], FunctorOnlys),
+ (
+ Inconsistents = [_ | _],
+ % Some clauses give two or more different names to HeadVar.
+ % If even a single clause cannot agree what HeadVar's name should be,
+ % the procedure as a whole cannot agree either.
+ MaybeConsensusName = no
+ ;
+ Inconsistents = [],
+ (
+ Consistents = [],
+ % There is no name we *can* give.
+ MaybeConsensusName = no
+ ;
+ Consistents = [_ | _],
+ (
+ FunctorOnlys = [],
+ list.sort_and_remove_dups(Consistents, SortedConsistents),
+ ( SortedConsistents = [ConsensusName] ->
+ MaybeConsensusName = yes(ConsensusName)
+ ;
+ MaybeConsensusName = no
+ )
+ ;
+ FunctorOnlys = [_ | _],
+ % There is no consensus as to whether the variable *should*
+ % have a name. Given a predicate definition like this:
+ %
+ % p(A, _) :- ...
+ % p([_ | _], _) :- ...
+ %
+ % referring to the first head variable in the second clause
+ % by the name "A" would be confusing.
+ MaybeConsensusName = no
+ )
+ )
+ ).
+
+:- pred group_var_infos(list(var_name_info_map)::in, prog_var::in,
+ list(var_name_info)::in, list(var_name_info)::out,
+ list(string)::in, list(string)::out,
+ list(var_name_info)::in, list(var_name_info)::out) is det.
+
+group_var_infos([], _, !Inconsistents, !Consistents, !FunctorOnlys).
+group_var_infos([VarNameInfoMap | VarNameInfoMaps], HeadVar,
+ !Inconsistents, !Consistents, !FunctorOnlys) :-
+ ( map.search(VarNameInfoMap, HeadVar, VarInfo) ->
+ VarInfo = var_name_info(UnifiedFunctor, VarNameSet),
+ set.count(VarNameSet, NameCount),
+ ( NameCount = 0 ->
+ (
+ UnifiedFunctor = yes,
+ !:FunctorOnlys = [VarInfo | !.FunctorOnlys]
+ ;
+ UnifiedFunctor = no
+ % The variable was unified only with anonymous variables.
+ )
+ ; NameCount = 1 ->
+ % If the clause gave the variable a name, we don't care that
+ % it also unified the variable with a functor.
+ set.to_sorted_list(VarNameSet, VarNameList),
+ ( VarNameList = [VarName] ->
+ !:Consistents = [VarName | !.Consistents]
+ ;
+ unexpected(this_file, "group_var_infos: bad singleton set")
+ )
+ ;
+ % NameCount > 1, so this *single clause* calls HeadVar
+ % by more than one name.
+ !:Inconsistents = [VarInfo | !.Inconsistents]
+ )
+ ;
+ true
+ ),
+ group_var_infos(VarNameInfoMaps, HeadVar,
+ !Inconsistents, !Consistents, !FunctorOnlys).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "headvar_names.m".
+
+%-----------------------------------------------------------------------------%
Index: hlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds.m,v
retrieving revision 1.222
diff -u -b -r1.222 hlds.m
--- hlds.m 21 Dec 2006 06:33:57 -0000 1.222
+++ hlds.m 14 May 2007 10:30:09 -0000
@@ -47,6 +47,7 @@
:- include_module code_model.
:- include_module goal_form.
:- include_module goal_util.
+:- include_module headvar_names.
:- include_module hlds_code_util.
:- include_module hlds_error_util.
:- include_module passes_aux.
Index: typecheck.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.421
diff -u -b -r1.421 typecheck.m
--- typecheck.m 14 May 2007 08:20:11 -0000 1.421
+++ typecheck.m 14 May 2007 10:31:39 -0000
@@ -108,6 +108,7 @@
:- import_module check_hlds.typecheck_info.
:- import_module check_hlds.typeclasses.
:- import_module hlds.goal_util.
+:- import_module hlds.headvar_names.
:- import_module hlds.hlds_args.
:- import_module hlds.hlds_clauses.
:- import_module hlds.hlds_data.
@@ -912,320 +913,6 @@
true
).
- % If there is only one clause, use the original head variables
- % from the clause rather than the introduced `HeadVar__n' variables
- % as the head variables in the proc_info.
- % This gives better error messages, more meaningful variable
- % names in the debugger and slightly faster compilation.
- %
-:- pred maybe_improve_headvar_names(globals::in, pred_info::in, pred_info::out)
- is det.
-
-maybe_improve_headvar_names(Globals, !PredInfo) :-
- pred_info_clauses_info(!.PredInfo, ClausesInfo0),
- clauses_info_clauses_only(ClausesInfo0, Clauses0),
- clauses_info_get_headvars(ClausesInfo0, HeadVars0),
- clauses_info_get_varset(ClausesInfo0, VarSet0),
- (
- % Don't do this when making a `.opt' file.
- % intermod.m needs to perform a similar transformation
- % which this transformation would interfere with (intermod.m
- % places the original argument terms, not just the argument
- % variables in the clause head, and this pass would make it
- % difficult to work out what were the original arguments).
- globals.lookup_bool_option(Globals, make_optimization_interface, yes)
- ->
- true
- ;
- Clauses0 = [SingleClause0]
- ->
- SingleClause0 = clause(ApplicableProcs, Goal0, Language, Context),
-
- Goal0 = hlds_goal(_, GoalInfo0),
- goal_to_conj_list(Goal0, Conj0),
- improve_single_clause_headvars(Conj0, HeadVars0, [],
- VarSet0, VarSet, map.init, Subst, [], RevConj),
-
- goal_info_get_nonlocals(GoalInfo0, NonLocals0),
- goal_util.rename_vars_in_var_set(no, Subst, NonLocals0, NonLocals),
- goal_info_set_nonlocals(NonLocals, GoalInfo0, GoalInfo),
- conj_list_to_goal(list.reverse(RevConj), GoalInfo, Goal),
-
- apply_renaming_to_proc_arg_vector(Subst, HeadVars0, HeadVars),
- clauses_info_set_headvars(HeadVars, ClausesInfo0, ClausesInfo1),
-
- SingleClause = clause(ApplicableProcs, Goal, Language, Context),
- clauses_info_set_clauses([SingleClause], ClausesInfo1, ClausesInfo2),
- clauses_info_set_varset(VarSet, ClausesInfo2, ClausesInfo),
- pred_info_set_clauses_info(ClausesInfo, !PredInfo)
- ;
- % If a headvar is assigned to a variable with the same name
- % (or no name) in every clause, rename it to have that name.
- list.map2(find_headvar_names_in_clause(VarSet0, HeadVars0), Clauses0,
- VarNameInfoMaps, VarsInMapSets),
- ConsensusMap = find_consensus_headvar_names(VarsInMapSets,
- VarNameInfoMaps),
- map.foldl(svvarset.name_var, ConsensusMap, VarSet0, VarSet),
- clauses_info_set_varset(VarSet, ClausesInfo0, ClausesInfo),
- pred_info_set_clauses_info(ClausesInfo, !PredInfo)
- ).
-
-:- pred improve_single_clause_headvars(list(hlds_goal)::in,
- proc_arg_vector(prog_var)::in, list(prog_var)::in,
- prog_varset::in, prog_varset::out,
- map(prog_var, prog_var)::in, map(prog_var, prog_var)::out,
- list(hlds_goal)::in, list(hlds_goal)::out) is det.
-
-improve_single_clause_headvars([], _, _, !VarSet, !Subst, !RevConj).
-improve_single_clause_headvars([Goal | Conj0], HeadVars, SeenVars0,
- !VarSet, !Subst, !RevConj) :-
- ( goal_is_headvar_unification(HeadVars, Goal, HeadVar, yes(OtherVar)) ->
- % If the headvar doesn't appear elsewhere the unification
- % can be removed.
- (
- % The headvars must be distinct variables, so check that this
- % variable doesn't already appear in the argument list.
- \+ proc_arg_vector_member(HeadVars, OtherVar),
- \+ list.member(OtherVar, SeenVars0),
-
- \+ ( some [OtherGoal] (
- ( list.member(OtherGoal, Conj0)
- ; list.member(OtherGoal, !.RevConj)
- ),
- OtherGoal = hlds_goal(_, OtherGoalInfo),
- goal_info_get_nonlocals(OtherGoalInfo, OtherNonLocals),
- set.member(HeadVar, OtherNonLocals)
- ))
- ->
- SeenVars = [OtherVar | SeenVars0],
- svmap.det_insert(HeadVar, OtherVar, !Subst),
-
- % If the variable wasn't named, use the `HeadVar__n' name.
- (
- \+ varset.search_name(!.VarSet, OtherVar, _),
- varset.search_name(!.VarSet, HeadVar, HeadVarName)
- ->
- svvarset.name_var(OtherVar, HeadVarName, !VarSet)
- ;
- true
- )
- ;
- !:RevConj = [Goal | !.RevConj],
- SeenVars = SeenVars0,
- ( varset.search_name(!.VarSet, OtherVar, OtherVarName) ->
- % The unification can't be eliminated,
- % so just rename the head variable.
- svvarset.name_var(HeadVar, OtherVarName, !VarSet)
- ; varset.search_name(!.VarSet, HeadVar, HeadVarName) ->
- % If the variable wasn't named, use the `HeadVar__n' name.
- svvarset.name_var(OtherVar, HeadVarName, !VarSet)
- ;
- true
- )
- )
- ;
- !:RevConj = [Goal | !.RevConj],
- SeenVars = SeenVars0
- ),
- improve_single_clause_headvars(Conj0, HeadVars, SeenVars, !VarSet,
- !Subst, !RevConj).
-
-:- type var_name_info_map == map(prog_var, var_name_info).
-:- type var_name_info
- ---> var_name_info(
- % Is the head variable unified with a functor?
- vni_unified_with_functor :: bool,
-
- % What are the names of the named variables it is unified with?
- vni_unified_with_vars :: set(string)
- ).
-
- % Head variables that have the same name in each clause
- % will have an entry of `yes(Name)' in the result map.
- %
-:- pred find_headvar_names_in_clause(prog_varset::in,
- proc_arg_vector(prog_var)::in, clause::in,
- var_name_info_map::out, set(prog_var)::out) is det.
-
-find_headvar_names_in_clause(VarSet, HeadVars, Clause, VarNameInfoMap,
- VarsInMap) :-
- Goal = Clause ^ clause_body,
- goal_to_conj_list(Goal, Conj),
- list.foldl2(find_headvar_names_in_goal(VarSet, HeadVars), Conj,
- map.init, VarNameInfoMap, set.init, VarsInMap).
-
-:- pred find_headvar_names_in_goal(prog_varset::in,
- proc_arg_vector(prog_var)::in, hlds_goal::in,
- var_name_info_map::in, var_name_info_map::out,
- set(prog_var)::in, set(prog_var)::out) is det.
-
-find_headvar_names_in_goal(VarSet, HeadVars, Goal, !VarNameInfoMap,
- !VarsInMap) :-
- ( goal_is_headvar_unification(HeadVars, Goal, HeadVar, MaybeOtherVar) ->
- svset.insert(HeadVar, !VarsInMap),
- (
- MaybeOtherVar = no,
- ( map.search(!.VarNameInfoMap, HeadVar, VarNameInfo0) ->
- VarNameInfo0 = var_name_info(_UnifiedFunctor, VarNames),
- VarNameInfo = var_name_info(yes, VarNames),
- svmap.det_update(HeadVar, VarNameInfo, !VarNameInfoMap)
- ;
- VarNameInfo = var_name_info(yes, set.init),
- svmap.det_insert(HeadVar, VarNameInfo, !VarNameInfoMap)
- )
- ;
- MaybeOtherVar = yes(OtherVar),
- ( varset.search_name(VarSet, OtherVar, OtherVarName) ->
- ( map.search(!.VarNameInfoMap, HeadVar, VarNameInfo0) ->
- VarNameInfo0 = var_name_info(UnifiedFunctor, VarNames0),
- set.insert(VarNames0, OtherVarName, VarNames),
- VarNameInfo = var_name_info(UnifiedFunctor, VarNames),
- svmap.det_update(HeadVar, VarNameInfo, !VarNameInfoMap)
- ;
- VarNames = set.make_singleton_set(OtherVarName),
- VarNameInfo = var_name_info(no, VarNames),
- svmap.det_insert(HeadVar, VarNameInfo, !VarNameInfoMap)
- )
- ;
- true
- )
- )
- ;
- true
- ).
-
-:- pred goal_is_headvar_unification(proc_arg_vector(prog_var)::in,
- hlds_goal::in, prog_var::out, maybe(prog_var)::out) is semidet.
-
-goal_is_headvar_unification(HeadVars, Goal, HeadVar, MaybeOtherVar) :-
- Goal = hlds_goal(GoalExpr, _),
- GoalExpr = unify(LVar, RHS, _, _, _),
- (
- RHS = rhs_var(RVar),
- ( proc_arg_vector_member(HeadVars, LVar) ->
- HeadVar = LVar,
- MaybeOtherVar = yes(RVar)
- ; proc_arg_vector_member(HeadVars, RVar) ->
- HeadVar = RVar,
- MaybeOtherVar = yes(LVar)
- ;
- fail
- )
- ;
- RHS = rhs_functor(_, _, _),
- ( proc_arg_vector_member(HeadVars, LVar) ->
- HeadVar = LVar,
- MaybeOtherVar = no
- ;
- fail
- )
- ).
-
-:- func find_consensus_headvar_names(list(set(prog_var)),
- list(var_name_info_map)) = map(prog_var, string).
-
-find_consensus_headvar_names(VarsInMapSets, VarNameInfoMaps) = ConsensusMap :-
- VarsInMapSet = set.union_list(VarsInMapSets),
- set.to_sorted_list(VarsInMapSet, VarsInMaps),
- list.foldl(update_consensus_map_for_headvar(VarNameInfoMaps), VarsInMaps,
- map.init, ConsensusMap).
-
-:- pred update_consensus_map_for_headvar(list(var_name_info_map)::in,
- prog_var::in,
- map(prog_var, string)::in, map(prog_var, string)::out) is det.
-
-update_consensus_map_for_headvar(VarNameInfos, HeadVar, !ConsensusMap) :-
- MaybeName = find_consensus_name_for_headvar(VarNameInfos, HeadVar),
- (
- MaybeName = no
- ;
- MaybeName = yes(Name),
- svmap.det_insert(HeadVar, Name, !ConsensusMap)
- ).
-
-:- func find_consensus_name_for_headvar(list(var_name_info_map), prog_var)
- = maybe(string).
-
-find_consensus_name_for_headvar(VarNameInfoMaps, HeadVar)
- = MaybeConsensusName :-
- group_var_infos(VarNameInfoMaps, HeadVar,
- [], Inconsistents, [], Consistents, [], FunctorOnlys),
- (
- Inconsistents = [_ | _],
- % Some clauses give two or more different names to HeadVar.
- % If even a single clause cannot agree what HeadVar's name should be,
- % the procedure as a whole cannot agree either.
- MaybeConsensusName = no
- ;
- Inconsistents = [],
- (
- Consistents = [],
- % There is no name we *can* give.
- MaybeConsensusName = no
- ;
- Consistents = [_ | _],
- (
- FunctorOnlys = [],
- list.sort_and_remove_dups(Consistents, SortedConsistents),
- ( SortedConsistents = [ConsensusName] ->
- MaybeConsensusName = yes(ConsensusName)
- ;
- MaybeConsensusName = no
- )
- ;
- FunctorOnlys = [_ | _],
- % There is no consensus as to whether the variable *should*
- % have a name. Given a predicate definition like this:
- %
- % p(A, _) :- ...
- % p([_ | _], _) :- ...
- %
- % referring to the first head variable in the second clause
- % by the name "A" would be confusing.
- MaybeConsensusName = no
- )
- )
- ).
-
-:- pred group_var_infos(list(var_name_info_map)::in, prog_var::in,
- list(var_name_info)::in, list(var_name_info)::out,
- list(string)::in, list(string)::out,
- list(var_name_info)::in, list(var_name_info)::out) is det.
-
-group_var_infos([], _, !Inconsistents, !Consistents, !FunctorOnlys).
-group_var_infos([VarNameInfoMap | VarNameInfoMaps], HeadVar,
- !Inconsistents, !Consistents, !FunctorOnlys) :-
- ( map.search(VarNameInfoMap, HeadVar, VarInfo) ->
- VarInfo = var_name_info(UnifiedFunctor, VarNameSet),
- set.count(VarNameSet, NameCount),
- ( NameCount = 0 ->
- (
- UnifiedFunctor = yes,
- !:FunctorOnlys = [VarInfo | !.FunctorOnlys]
- ;
- UnifiedFunctor = no
- % The variable was unified only with anonymous variables.
- )
- ; NameCount = 1 ->
- % If the clause gave the variable a name, we don't care that
- % it also unified the variable with a functor.
- set.to_sorted_list(VarNameSet, VarNameList),
- ( VarNameList = [VarName] ->
- !:Consistents = [VarName | !.Consistents]
- ;
- unexpected(this_file, "group_var_infos: bad singleton set")
- )
- ;
- % NameCount > 1, so this *single clause* calls HeadVar
- % by more than one name.
- !:Inconsistents = [VarInfo | !.Inconsistents]
- )
- ;
- true
- ),
- group_var_infos(VarNameInfoMaps, HeadVar,
- !Inconsistents, !Consistents, !FunctorOnlys).
-
%-----------------------------------------------------------------------------%
% Iterate over the list of clauses for a predicate.
cvs diff: Diffing notes
Index: notes/compiler_design.html
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.126
diff -u -b -r1.126 compiler_design.html
--- notes/compiler_design.html 11 Jan 2007 03:36:01 -0000 1.126
+++ notes/compiler_design.html 14 May 2007 10:29:26 -0000
@@ -615,6 +615,14 @@
consistent with any types in scope.
<p>
+<dt> improving the names of head variables
+ <dd>
+ headvar_names.m tries to replace names of the form HeadVar__n
+ with actual names given by the programmer.
+ <p>
+ For efficiency, this phase not a standalone pass,
+ but is instead invoked by the typechecker.
+
<dt> type checking
<dd>
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list