diff: fix for bug in switch detection

Fergus Henderson fjh at cs.mu.oz.au
Sun May 11 02:20:46 AEST 1997


compiler/switch_detection.m:
	Fix a bug.  It was preferring incomplete switches to
	complete one-case switches, which lead to spurious determinism
	errors in some cases.

Index: switch_detection.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/switch_detection.m,v
retrieving revision 1.69
diff -u -r1.69 switch_detection.m
--- switch_detection.m	1997/05/08 06:46:56	1.69
+++ switch_detection.m	1997/05/10 16:16:19
@@ -214,16 +214,44 @@
 		inst_is_bound(ModuleInfo, VarInst0),
 		partition_disj(Goals0, Var, GoalInfo, Left, CasesList)
 	->
-		% are there any disjuncts that are not part of the switch?
+		%
+		% A switch needs to have at least two cases.
+		%
+		% But, if there is a complete one-case switch
+		% for a goal, we must leave it as a disjunction
+		% rather than doing an incomplete switch on a
+		% different variable, because otherwise we might
+		% get determinism analysis wrong.  (The complete
+		% one-case switch may be decomposable into other
+		% complete sub-switches on the functor's arguments)
+		%
 		(
+			% are there any disjuncts that are not part of the
+			% switch?
 			Left = []
 		->
-			cases_to_switch(CasesList, Var, VarTypes, GoalInfo,
-				SM, InstMap, ModuleInfo, Goal)
+			( CasesList = [_, _ | _] ->
+				cases_to_switch(CasesList, Var, VarTypes,
+					GoalInfo, SM, InstMap, ModuleInfo,
+					Goal)
+			;
+				detect_sub_switches_in_disj(Goals0, InstMap,
+					VarTypes, ModuleInfo, Goals),
+				Goal = disj(Goals, SM)
+			)
 		;
+			% insert this switch into the list of incomplete
+			% switches only if it has at least two cases
+			%
+			( CasesList = [_, _ | _] ->
+				Again1 = [again(Var, Left, CasesList) | Again0]
+			;
+				Again1 = Again0
+			),
+			% try to find a switch
 			detect_switches_in_disj(Vars, Goals0, GoalInfo,
 				SM, InstMap, VarTypes, AllVars, ModuleInfo,
-				[again(Var, Left, CasesList) | Again0], Goal)
+				Again1, Goal)
 		)
 	;
 		detect_switches_in_disj(Vars, Goals0, GoalInfo, SM, InstMap,
@@ -322,8 +350,8 @@
 	map__init(Cases0),
 	partition_disj_trial(Goals0, Var, [], Left, Cases0, Cases),
 	map__to_assoc_list(Cases, CasesAssocList),
-	fix_case_list(CasesAssocList, GoalInfo, CasesList),
-	CasesList = [_, _ | _].	% there must be more than one case
+	CasesAssocList \= [],
+	fix_case_list(CasesAssocList, GoalInfo, CasesList).
 
 :- pred partition_disj_trial(list(hlds_goal), var,
 	list(hlds_goal), list(hlds_goal), cases, cases).
-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list