MODULE M3CRaisesSet;
*************************************************************************
Copyright (C) Olivetti 1989
All Rights reserved
Use and copy of this software and preparation of derivative works based
upon this software are permitted to any person, provided this same
copyright notice and the following Olivetti warranty disclaimer are
included in any copy of the software or any modification thereof or
derivative work therefrom made by any person.
This software is made available AS IS and Olivetti disclaims all
warranties with respect to this software, whether expressed or implied
under any law, including all implied warranties of merchantibility and
fitness for any purpose. In no event shall Olivetti be liable for any
damages whatsoever resulting from loss of use, data or profits or
otherwise arising out of or in connection with the use or performance
of this software.
*************************************************************************
Copyright
IMPORT M3AST_AS, M3AST_SM;
IMPORT M3AST_AS_F, M3AST_SM_F;
IMPORT SeqM3AST_AS_Qual_used_id;
The algorithm used is only suitable for small RAISES lists but then most
RAISES lists are small. It allows duplication in RAISES lists
TYPE
DefIdList = RECORD
array: ARRAY [0..15] OF RECORD defId: M3AST_AS.DEF_ID; mark: CARDINAL END;
count: CARDINAL;
next: REF DefIdList;
END;
TYPE
InList = {Nil, Absent, PresentSameMark, PresentOtherMark};
VAR (* CONST *)
null_raisees_some_g := NEW(M3AST_AS.Raisees_some).init();
PROCEDURE Check(
defId: M3AST_SM.DEF_ID_UNSET;
mark: CARDINAL;
VAR list: DefIdList)
: InList
RAISES {}=
BEGIN
IF defId = NIL THEN RETURN InList.Nil END;
FOR i := 0 TO list.count - 1 DO
WITH entry = list.array[i] DO
IF entry.defId = defId THEN
IF entry.mark = mark THEN
RETURN InList.PresentSameMark;
ELSE
entry.mark := mark;
RETURN InList.PresentOtherMark;
END;
END;
END;
END;
IF list.count = NUMBER(list.array) THEN
IF list.next = NIL THEN
list.next := NEW(REF DefIdList, count := 0, next := NIL)
END;
RETURN Check(defId, mark, list.next^);
ELSE
WITH entry = list.array[list.count] DO
entry.defId := defId;
entry.mark := mark;
END;
INC(list.count);
RETURN InList.Absent;
END;
END Check;
PROCEDURE Compare(xr1, xr2: M3AST_AS.RAISEES_NULL): Comparison RAISES {}=
VAR r1, r2: M3AST_AS.Raisees_some;
BEGIN
IF xr1 = NIL THEN r1 := null_raisees_some_g
ELSIF ISTYPE(xr1, M3AST_AS.Raisees_any) THEN r1 := NIL;
ELSE r1 := xr1
END;
IF xr2 = NIL THEN r2 := null_raisees_some_g
ELSIF ISTYPE(xr2, M3AST_AS.Raisees_any) THEN r2 := NIL;
ELSE r2 := xr2
END;
IF r1 # NIL AND r2 # NIL THEN
VAR
dl: DefIdList;
r: M3AST_AS.Raisees_some;
iter: SeqM3AST_AS_Qual_used_id.Iter;
qualId: M3AST_AS.Qual_used_id;
count1, count2 := 0;
BEGIN
dl.next := NIL;
dl.count := 0;
FOR i := 1 TO 2 DO
IF i = 1 THEN r := r1 ELSE r := r2 END;
iter := SeqM3AST_AS_Qual_used_id.NewIter(r.as_raisees_s);
WHILE SeqM3AST_AS_Qual_used_id.Next(iter, qualId) DO
WITH inList = Check(qualId.as_id.sm_def, i, dl) DO
IF i = 1 THEN
IF inList = InList.Absent THEN INC(count1) END;
ELSE
CASE inList OF
| InList.Absent =>
INC(count2);
IF count1 = 0 THEN
RETURN Comparison.ProperSubSet;
END;
| InList.PresentOtherMark =>
DEC(count1);
IF count1 = 0 AND count2 > 0 THEN
RETURN Comparison.ProperSubSet
END;
ELSE
END;
END;
END;
END;
END;
IF count1 = 0 THEN
RETURN Comparison.Equal;
ELSIF count2 = 0 THEN
RETURN Comparison.ProperSuperSet;
ELSE
RETURN Comparison.Disjoint;
END;
END;
ELSIF r1 = NIL AND r2 = NIL THEN
(* neither has raises clause *)
RETURN Comparison.Equal;
ELSE
(* only one has raises clause; the one without the raises clause is
a superset of the other (because no raises clause => raises set of
all exceptions) *)
IF r1 = NIL THEN
RETURN Comparison.ProperSuperSet;
ELSE
RETURN Comparison.ProperSubSet;
END; (* if *)
END; (* if *)
END Compare;
BEGIN
END M3CRaisesSet.