[m-rev.] diff: improve the handling of foreign_proc goals in goal_form.m
Julien Fischer
juliensf at cs.mu.OZ.AU
Fri Apr 1 18:37:00 AEST 2005
Estimated hours taken: 0.5
Branches: main
Improve the way that the predicates that test whether a goal
loops or throws an exception handle foreign_proc goals.
compiler/goal_form.m:
When working out whether goals can loop or throw exceptions
apply the documented default behaviour for foreign_procs.
Clean up the formatting of comments in this module.
Change calls to error/1 to calls to unexpected/2.
Other minor cleanups.
Julien.
Index: compiler/goal_form.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/goal_form.m,v
retrieving revision 1.13
diff -u -r1.13 goal_form.m
--- compiler/goal_form.m 24 Mar 2005 05:34:02 -0000 1.13
+++ compiler/goal_form.m 1 Apr 2005 08:29:22 -0000
@@ -27,21 +27,27 @@
%
% Succeeds if the goal cannot loop forever.
+ %
:- pred goal_cannot_loop(module_info::in, hlds_goal::in) is semidet.
% Succeeds if the goal can loop forever.
+ %
:- pred goal_can_loop(module_info::in, hlds_goal::in) is semidet.
% Succeeds if the goal cannot throw an exception.
+ %
:- pred goal_cannot_throw(module_info::in, hlds_goal::in) is semidet.
% Succeeds if the goal can throw an exception.
+ %
:- pred goal_can_throw(module_info::in, hlds_goal::in) is semidet.
% Succeeds if the goal cannot loop forever or throw an exception.
+ %
:- pred goal_cannot_loop_or_throw(module_info::in, hlds_goal::in) is semidet.
% Succeeds if the goal can loop forever or throw an exception.
+ %
:- pred goal_can_loop_or_throw(module_info::in, hlds_goal::in) is semidet.
%
@@ -50,64 +56,66 @@
%
% Succeeds if the goal cannot loop forever or throw an exception.
+ %
:- pred goal_cannot_loop_or_throw(hlds_goal::in) is semidet.
% Succeed if the goal can loop forever or throw an exception.
+ %
:- pred goal_can_loop_or_throw(hlds_goal::in) is semidet.
% contains_only_builtins(G) is true if G is a leaf procedure,
- % i.e. control does not leave G to call another procedure, even if
- % that procedure is a complicated unification.
-
+ % i.e. control does not leave G to call another procedure, even
+ % if that procedure is a complicated unification.
+ %
:- pred contains_only_builtins(hlds_goal::in) is semidet.
:- pred contains_only_builtins_expr(hlds_goal_expr::in) is semidet.
:- pred contains_only_builtins_list(list(hlds_goal)::in) is semidet.
- % goal_is_flat(Goal) is true if Goal does not contain
- % any branched structures (ie if-then-else or disjunctions or
+ % goal_is_flat(Goal) is true if Goal does not contain any
+ % branched structures (ie if-then-else or disjunctions or
% switches.)
+ %
:- pred goal_is_flat(hlds_goal::in) is semidet.
- % Determine whether a goal might allocate some heap space,
- % i.e. whether it contains any construction unifications
- % or predicate calls. BEWARE that this predicate is only
- % an approximation, used to decide whether or not to try to
- % reclaim the heap space; currently it fails even for some
- % goals which do allocate heap space, such as construction
- % of boxed constants.
-
+ % Determine whether a goal might allocate some heap space, i.e.
+ % whether it contains any construction unifications or predicate
+ % calls. BEWARE that this predicate is only an approximation,
+ % used to decide whether or not to try to reclaim the heap
+ % space; currently it fails even for some goals which do
+ % allocate heap space, such as construction of boxed constants.
+ %
:- pred goal_may_allocate_heap(hlds_goal::in) is semidet.
:- pred goal_list_may_allocate_heap(list(hlds_goal)::in) is semidet.
% Succeed if execution of the given goal cannot encounter a context
- % that causes any variable to be flushed to its stack slot.
- % If such a goal needs a resume point, and that resume point cannot
- % be backtracked to once control leaves the goal, then the only entry
+ % that causes any variable to be flushed to its stack slot. If such a
+ % goal needs a resume point, and that resume point cannot be
+ % backtracked to once control leaves the goal, then the only entry
% point we need for the resume point is the one with the resume
% variables in their original locations.
-
+ %
:- pred cannot_stack_flush(hlds_goal::in) is semidet.
% Succeed if execution of the given goal cannot encounter a context
% that causes any variable to be flushed to its stack slot or to a
% register.
-
+ %
:- pred cannot_flush(hlds_goal::in) is semidet.
- % Succeed if the given goal cannot fail before encountering a context
- % that forces all variables to be flushed to their stack slots.
- % If such a goal needs a resume point, the only entry point we need
- % is the stack entry point.
-
+ % Succeed if the given goal cannot fail before encountering a
+ % context that forces all variables to be flushed to their stack
+ % slots. If such a goal needs a resume point, the only entry
+ % point we need is the stack entry point.
+ %
:- pred cannot_fail_before_stack_flush(hlds_goal::in) is semidet.
- % count_recursive_calls(Goal, PredId, ProcId, Min, Max)
- % Given that we are in predicate PredId and procedure ProcId,
- % return the minimum and maximum number of recursive calls that
- % an execution of Goal may encounter.
-
+ % count_recursive_calls(Goal, PredId, ProcId, Min, Max). Given
+ % that we are in predicate PredId and procedure ProcId, return
+ % the minimum and maximum number of recursive calls that an
+ % execution of Goal may encounter.
+ %
:- pred count_recursive_calls(hlds_goal::in, pred_id::in, proc_id::in,
int::out, int::out) is det.
@@ -117,13 +125,13 @@
:- implementation.
:- import_module hlds__hlds_data.
+:- import_module parse_tree__error_util.
:- import_module parse_tree__prog_data.
:- import_module transform_hlds__term_util.
:- import_module bool.
:- import_module int.
:- import_module map.
-:- import_module require.
:- import_module std_util.
%-----------------------------------------------------------------------------%
@@ -132,7 +140,7 @@
goal_cannot_loop_aux(yes(ModuleInfo), Goal).
goal_can_loop(ModuleInfo, Goal) :-
- \+ goal_cannot_loop(ModuleInfo, Goal).
+ not goal_cannot_loop(ModuleInfo, Goal).
goal_cannot_throw(ModuleInfo, Goal) :-
goal_cannot_throw_aux(yes(ModuleInfo), Goal).
@@ -178,13 +186,21 @@
goal_cannot_loop_aux(MaybeModuleInfo, Goal).
goal_cannot_loop_expr(MaybeModuleInfo, scope(_, Goal)) :-
goal_cannot_loop_aux(MaybeModuleInfo, Goal).
-goal_cannot_loop_expr(MaybeModuleInfo,
- if_then_else(_Vars, Cond, Then, Else)) :-
+goal_cannot_loop_expr(MaybeModuleInfo, Goal) :-
+ Goal = if_then_else(_Vars, Cond, Then, Else),
goal_cannot_loop_aux(MaybeModuleInfo, Cond),
goal_cannot_loop_aux(MaybeModuleInfo, Then),
goal_cannot_loop_aux(MaybeModuleInfo, Else).
-goal_cannot_loop_expr(MaybeModuleInfo,
- call(PredId, ProcId, _, _, _, _)) :-
+goal_cannot_loop_expr(_MaybeModuleInfo, Goal) :-
+ Goal = foreign_proc(Attributes, _, _, _, _, _),
+ (
+ terminates(Attributes) = terminates
+ ;
+ terminates(Attributes) = depends_on_mercury_calls,
+ may_call_mercury(Attributes) = will_not_call_mercury
+ ).
+goal_cannot_loop_expr(MaybeModuleInfo, Goal) :-
+ Goal = call(PredId, ProcId, _, _, _, _),
MaybeModuleInfo = yes(ModuleInfo),
module_info_pred_proc_info(ModuleInfo, PredId, ProcId, _, ProcInfo),
proc_info_get_maybe_termination_info(ProcInfo, MaybeTermInfo),
@@ -209,7 +225,9 @@
:- pred goal_cannot_throw_aux(maybe(module_info)::in,
hlds_goal::in) is semidet.
-goal_cannot_throw_aux(MaybeModuleInfo, GoalExpr - _) :-
+goal_cannot_throw_aux(MaybeModuleInfo, GoalExpr - GoalInfo) :-
+ goal_info_get_determinism(GoalInfo, Determinism),
+ not Determinism = erroneous,
goal_cannot_throw_expr(MaybeModuleInfo, GoalExpr).
:- pred goal_cannot_throw_expr(maybe(module_info)::in,
@@ -228,12 +246,22 @@
goal_cannot_throw_aux(MaybeModuleInfo, Goal).
goal_cannot_throw_expr(MaybeModuleInfo, scope(_, Goal)) :-
goal_cannot_throw_aux(MaybeModuleInfo, Goal).
-goal_cannot_throw_expr(MaybeModuleInfo, if_then_else(_, Cond, Then, Else)) :-
+goal_cannot_throw_expr(MaybeModuleInfo, Goal) :-
+ Goal = if_then_else(_, Cond, Then, Else),
goal_cannot_throw_aux(MaybeModuleInfo, Cond),
goal_cannot_throw_aux(MaybeModuleInfo, Then),
goal_cannot_throw_aux(MaybeModuleInfo, Else).
-goal_cannot_loop_expr(MaybeModuleInfo,
- call(PredId, ProcId, _, _, _, _)) :-
+goal_cannot_throw_expr(_MaybeModuleInfo, Goal) :-
+ Goal = foreign_proc(Attributes, _, _, _, _, _),
+ ExceptionStatus = may_throw_exception(Attributes),
+ (
+ ExceptionStatus = will_not_throw_exception
+ ;
+ ExceptionStatus = default_exception_behaviour,
+ may_call_mercury(Attributes) = will_not_call_mercury
+ ).
+goal_cannot_loop_expr(MaybeModuleInfo, Goal) :-
+ Goal = call(PredId, ProcId, _, _, _, _),
MaybeModuleInfo = yes(ModuleInfo),
module_info_exception_info(ModuleInfo, ExceptionInfo),
map.search(ExceptionInfo, proc(PredId, ProcId), will_not_throw).
@@ -541,7 +569,7 @@
int__max(CTMax, EMax, Max).
count_recursive_calls_2(shorthand(_), _, _, _, _) :-
% these should have been expanded out by now
- error("count_recursive_calls_2: unexpected shorthand").
+ unexpected(this_file, "count_recursive_calls_2: unexpected shorthand").
:- pred count_recursive_calls_conj(list(hlds_goal)::in,
pred_id::in, proc_id::in, int::in, int::in, int::out, int::out) is det.
@@ -573,20 +601,24 @@
int::out, int::out) is det.
count_recursive_calls_cases([], _, _, _, _) :-
- error("empty cases in count_recursive_calls_cases").
+ unexpected(this_file, "empty cases in count_recursive_calls_cases").
count_recursive_calls_cases([case(_, Goal) | Cases], PredId, ProcId,
Min, Max) :-
( Cases = [] ->
- count_recursive_calls(Goal, PredId, ProcId,
- Min, Max)
+ count_recursive_calls(Goal, PredId, ProcId, Min, Max)
;
- count_recursive_calls(Goal, PredId, ProcId,
- Min0, Max0),
+ count_recursive_calls(Goal, PredId, ProcId, Min0, Max0),
count_recursive_calls_cases(Cases, PredId, ProcId,
Min1, Max1),
int__min(Min0, Min1, Min),
int__max(Max0, Max1, Max)
).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "goal_form.m".
%-----------------------------------------------------------------------------%
:- end_module goal_form.
--------------------------------------------------------------------------
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