[m-rev.] for review: fix infinite loop for `:- inst x == x.'

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Nov 21 06:23:43 AEDT 2002


Estimated hours taken: 1
Branches: main, release

compiler/inst_match.m:
	Fix a bug where the compiler was going into an infinite loop
	for infinitely recursive insts, e.g. `:- inst foo == foo.'

	XXX Note that we still don't handle cases such as
	`:- inst foo(I) == foo(list(I))' correctly.
	In those cases, the compiler will eventually run out of heap space.

Workspace: /home/mars/fjh/ws1/mercury
Index: compiler/inst_match.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/inst_match.m,v
retrieving revision 1.50
diff -u -d -r1.50 inst_match.m
--- compiler/inst_match.m	20 Mar 2002 12:36:24 -0000	1.50
+++ compiler/inst_match.m	20 Nov 2002 19:16:37 -0000
@@ -159,7 +159,8 @@
 /*
 ** Predicates to test various properties of insts.
 ** Note that `not_reached' insts are considered to satisfy
-** all of these predicates except inst_is_clobbered.
+** all of these predicates except inst_is_clobbered, inst_is_free,
+** and inst_is_bound_to_functors.
 */
 
         % succeed if the inst is fully ground (i.e. contains only
@@ -196,6 +197,7 @@
 :- pred inst_is_not_fully_unique(module_info, inst).
 :- mode inst_is_not_fully_unique(in, in) is semidet.
 
+        % succeed if the inst passed is `clobbered' or `mostly_clobbered'
 :- pred inst_is_clobbered(module_info, inst).
 :- mode inst_is_clobbered(in, in) is semidet.
 
@@ -776,9 +778,24 @@
 %-----------------------------------------------------------------------------%
 
 inst_expand(ModuleInfo, Inst0, Inst) :-
+	set__init(Expansions),
+	inst_expand_2(ModuleInfo, Inst0, Expansions, Inst).
+
+:- pred inst_expand_2(module_info, inst, set(inst_name), inst).
+:- mode inst_expand_2(in, in, in, out) is det.
+
+inst_expand_2(ModuleInfo, Inst0, Expansions0, Inst) :-
 	( Inst0 = defined_inst(InstName) ->
-		inst_lookup(ModuleInfo, InstName, Inst1),
-		inst_expand(ModuleInfo, Inst1, Inst)
+		( set__member(InstName, Expansions0) ->
+			% The inst is an infinitely recursive inst,
+			% e.g. `:- inst foo == foo.'
+			% We treat these as equivalent to `not_reached'.
+			Inst = not_reached
+		;
+			set__insert(Expansions0, InstName, Expansions1),
+			inst_lookup(ModuleInfo, InstName, Inst1),
+			inst_expand_2(ModuleInfo, Inst1, Expansions1, Inst)
+		)
 	;
 		Inst = Inst0
 	).
@@ -1080,65 +1097,141 @@
         % or `mostly_clobbered' or if it is a user-defined inst which
         % is defined as one of those.
 
-inst_is_clobbered(_, not_reached) :- fail.
-inst_is_clobbered(_, any(mostly_clobbered)).
-inst_is_clobbered(_, any(clobbered)).
-inst_is_clobbered(_, ground(clobbered, _)).
-inst_is_clobbered(_, ground(mostly_clobbered, _)).
-inst_is_clobbered(_, bound(clobbered, _)).
-inst_is_clobbered(_, bound(mostly_clobbered, _)).
-inst_is_clobbered(_, inst_var(_)) :-
+        % The third arg for the _2 version is the set of insts which have
+        % already been expanded - we use this to avoid going into an
+        % infinite loop for infinitely recursive insts.
+
+inst_is_clobbered(ModuleInfo, Inst) :-
+	set__init(Expansions),
+	inst_is_clobbered_2(ModuleInfo, Inst, Expansions).
+
+:- pred inst_is_clobbered_2(module_info, inst, set(inst_name)).
+:- mode inst_is_clobbered_2(in, in, in) is semidet.
+inst_is_clobbered_2(_, not_reached, _) :- fail.
+inst_is_clobbered_2(_, any(mostly_clobbered), _).
+inst_is_clobbered_2(_, any(clobbered), _).
+inst_is_clobbered_2(_, ground(clobbered, _), _).
+inst_is_clobbered_2(_, ground(mostly_clobbered, _), _).
+inst_is_clobbered_2(_, bound(clobbered, _), _).
+inst_is_clobbered_2(_, bound(mostly_clobbered, _), _).
+inst_is_clobbered_2(_, inst_var(_), _) :-
         error("internal error: uninstantiated inst parameter").
-inst_is_clobbered(ModuleInfo, constrained_inst_vars(_, Inst)) :-
-	inst_is_clobbered(ModuleInfo, Inst).
-inst_is_clobbered(ModuleInfo, defined_inst(InstName)) :-
-        inst_lookup(ModuleInfo, InstName, Inst),
-        inst_is_clobbered(ModuleInfo, Inst).
+inst_is_clobbered_2(ModuleInfo, constrained_inst_vars(_, Inst), Expansions) :-
+	inst_is_clobbered_2(ModuleInfo, Inst, Expansions).
+inst_is_clobbered_2(ModuleInfo, defined_inst(InstName), Expansions0) :-
+        ( set__member(InstName, Expansions0) ->
+		% It's an infinitely recursive inst,
+		% e.g. :- inst foo == foo.
+		% We treat these as equivalent to `not_reached' insts.
+                fail
+        ;
+                set__insert(Expansions0, InstName, Expansions),
+		inst_lookup(ModuleInfo, InstName, Inst),
+		inst_is_clobbered_2(ModuleInfo, Inst, Expansions)
+	).
 
         % inst_is_free succeeds iff the inst passed is `free'
         % or is a user-defined inst which is defined as `free'.
         % Abstract insts must not be free.
 
-inst_is_free(_, free).
-inst_is_free(_, free(_Type)).
-inst_is_free(_, inst_var(_)) :-
+        % The third arg for the _2 version is the set of insts which have
+        % already been expanded - we use this to avoid going into an
+        % infinite loop for infinitely recursive insts.
+
+inst_is_free(ModuleInfo, Inst) :-
+	set__init(Expansions),
+	inst_is_free_2(ModuleInfo, Inst, Expansions).
+
+:- pred inst_is_free_2(module_info, inst, set(inst_name)).
+:- mode inst_is_free_2(in, in, in) is semidet.
+inst_is_free_2(_, not_reached, _) :- fail.
+inst_is_free_2(_, free, _).
+inst_is_free_2(_, free(_Type), _).
+inst_is_free_2(_, inst_var(_), _) :-
         error("internal error: uninstantiated inst parameter").
-inst_is_free(ModuleInfo, constrained_inst_vars(_, Inst)) :-
-	inst_is_free(ModuleInfo, Inst).
-inst_is_free(ModuleInfo, defined_inst(InstName)) :-
-        inst_lookup(ModuleInfo, InstName, Inst),
-        inst_is_free(ModuleInfo, Inst).
+inst_is_free_2(ModuleInfo, constrained_inst_vars(_, Inst), Expansions) :-
+	inst_is_free_2(ModuleInfo, Inst, Expansions).
+inst_is_free_2(ModuleInfo, defined_inst(InstName), Expansions0) :-
+	( set__member(InstName, Expansions0) ->
+		% It's an infinitely recursive inst,
+		% e.g. :- inst foo == foo.
+		% We treat these as equivalent to `not_reached' insts.
+                fail
+        ;
+                set__insert(Expansions0, InstName, Expansions),
+		inst_lookup(ModuleInfo, InstName, Inst),
+		inst_is_free_2(ModuleInfo, Inst, Expansions)
+	).
 
         % inst_is_bound succeeds iff the inst passed is not `free'
         % or is a user-defined inst which is not defined as `free'.
         % Abstract insts must be bound.
 
-inst_is_bound(_, not_reached).
-inst_is_bound(_, any(_)).
-inst_is_bound(_, ground(_, _)).
-inst_is_bound(_, bound(_, _)).
-inst_is_bound(_, inst_var(_)) :-
+        % The third arg for the _2 version is the set of insts which have
+        % already been expanded - we use this to avoid going into an
+        % infinite loop for infinitely recursive insts.
+
+inst_is_bound(ModuleInfo, Inst) :-
+	set__init(Expansions),
+	inst_is_free_2(ModuleInfo, Inst, Expansions).
+
+:- pred inst_is_bound_2(module_info, inst, set(inst_name)).
+:- mode inst_is_bound_2(in, in, in) is semidet.
+inst_is_bound_2(_, not_reached, _).
+inst_is_bound_2(_, any(_), _).
+inst_is_bound_2(_, ground(_, _), _).
+inst_is_bound_2(_, bound(_, _), _).
+inst_is_bound_2(_, inst_var(_), _) :-
         error("internal error: uninstantiated inst parameter").
-inst_is_bound(ModuleInfo, constrained_inst_vars(_, Inst)) :-
-	inst_is_bound(ModuleInfo, Inst).
-inst_is_bound(ModuleInfo, defined_inst(InstName)) :-
-        inst_lookup(ModuleInfo, InstName, Inst),
-        inst_is_bound(ModuleInfo, Inst).
-inst_is_bound(_, abstract_inst(_, _)).
+inst_is_bound_2(ModuleInfo, constrained_inst_vars(_, Inst), Expansions) :-
+	inst_is_bound_2(ModuleInfo, Inst, Expansions).
+inst_is_bound_2(ModuleInfo, defined_inst(InstName), Expansions0) :-
+	( set__member(InstName, Expansions0) ->
+		% It's an infinitely recursive inst,
+		% e.g. :- inst foo == foo.
+		% We treat these as equivalent to `not_reached' insts.
+                true
+        ;
+                set__insert(Expansions0, InstName, Expansions),
+		inst_lookup(ModuleInfo, InstName, Inst),
+		inst_is_bound_2(ModuleInfo, Inst, Expansions)
+	).
+inst_is_bound_2(_, abstract_inst(_, _), _).
 
         % inst_is_bound_to_functors succeeds iff the inst passed is
         % `bound(_Uniq, Functors)' or is a user-defined inst which expands to
         % `bound(_Uniq, Functors)'.
 
-inst_is_bound_to_functors(_, bound(_Uniq, Functors), Functors).
-inst_is_bound_to_functors(_, inst_var(_), _) :-
+        % The third arg for the _2 version is the set of insts which have
+        % already been expanded - we use this to avoid going into an
+        % infinite loop for infinitely recursive insts.
+
+inst_is_bound_to_functors(ModuleInfo, Inst, Functors) :-
+	set__init(Expansions),
+	inst_is_bound_to_functors_2(ModuleInfo, Inst, Functors, Expansions).
+
+:- pred inst_is_bound_to_functors_2(module_info, inst, list(bound_inst),
+		set(inst_name)).
+:- mode inst_is_bound_to_functors_2(in, in, out, in) is semidet.
+inst_is_bound_to_functors_2(_, bound(_Uniq, Functors), Functors, _).
+inst_is_bound_to_functors_2(_, inst_var(_), _, _) :-
         error("internal error: uninstantiated inst parameter").
-inst_is_bound_to_functors(ModuleInfo, constrained_inst_vars(_, Inst),
-		Functors) :-
-	inst_is_bound_to_functors(ModuleInfo, Inst, Functors).
-inst_is_bound_to_functors(ModuleInfo, defined_inst(InstName), Functors) :-
-        inst_lookup(ModuleInfo, InstName, Inst),
-        inst_is_bound_to_functors(ModuleInfo, Inst, Functors).
+inst_is_bound_to_functors_2(ModuleInfo, constrained_inst_vars(_, Inst),
+		Functors, Expansions) :-
+	inst_is_bound_to_functors_2(ModuleInfo, Inst, Functors, Expansions).
+inst_is_bound_to_functors_2(ModuleInfo, defined_inst(InstName), Functors,
+		Expansions0) :-
+	( set__member(InstName, Expansions0) ->
+		% It's an infinitely recursive inst,
+		% e.g. :- inst foo == foo.
+		% We treat these as equivalent to `not_reached' insts.
+                fail
+        ;
+                set__insert(Expansions0, InstName, Expansions),
+		inst_lookup(ModuleInfo, InstName, Inst),
+		inst_is_bound_to_functors_2(ModuleInfo, Inst, Functors,
+			Expansions)
+	).
 
 %-----------------------------------------------------------------------------%
 

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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