set/src/SetList.mg


 Copyright 1993 Digital Equipment Corporation. 
 Distributed only by permission. 
 See the file COPYRIGHT for a full description. 
 Last modified on Mon Jul 25 11:51:56 PDT 1994 by detlefs 

GENERIC MODULE SetList(Elem, ElemSet, ElemList);
WHERE ElemSet = Set(Elem), and ElemList = List(Elem).

REVEAL
  T = Public BRANDED OBJECT
    l: ElemList.T := NIL
   OVERRIDES
    init := Init;
    fromArray := FromArray;
    copy := Copy;
    member := Member;
    insert := Insert;
    delete := Delete;
    size := Size;
    intersection := Intersection;
    diff := Diff;
    intersectionD := IntersectionD;
    diffD := DiffD;
    iterate := Iterate;
  END (* OBJECT *);

  Iterator = ElemSet.Iterator BRANDED OBJECT
    l: ElemList.T
   OVERRIDES
    next := Next;
  END (* OBJECT *);

PROCEDURE Init(s: T): T =
  BEGIN RETURN s END Init;

PROCEDURE FromArray(s: T; READONLY a: ARRAY OF Elem.T): ElemSet.T =
  BEGIN
    s.l := NIL;
    FOR i := 0 TO LAST(a) DO EVAL s.insert(a[i]) END (* FOR *);
    RETURN s
  END FromArray;

PROCEDURE Copy(s: T): ElemSet.T =
  VAR res := NEW(T).init(); rl := s.l; BEGIN
    WHILE rl # NIL DO
      res.l := ElemList.Cons(rl.head, res.l);
      rl := rl.tail
    END (* WHILE *);
    RETURN res
  END Copy;

PROCEDURE Member(s: T; e: Elem.T): BOOLEAN =
  VAR rl := s.l; BEGIN
    WHILE rl # NIL DO
      IF Elem.Equal(rl.head, e) THEN RETURN TRUE END (* IF *);
      rl := rl.tail
    END (* WHILE *);
    RETURN FALSE
  END Member;

PROCEDURE Insert(s: T; e: Elem.T): BOOLEAN =
  BEGIN
    IF s.member(e) THEN
      RETURN TRUE
    ELSE
      s.l := ElemList.Cons(e, s.l);
      RETURN FALSE
    END (* IF *)
  END Insert;

PROCEDURE Delete(s: T; e: Elem.T): BOOLEAN =
  VAR pl: ElemList.T := NIL; rl := s.l; BEGIN
    WHILE rl # NIL DO
      IF Elem.Equal(e, rl.head) THEN
        IF pl = NIL THEN
          s.l := rl.tail
        ELSE
          pl.tail := rl.tail
        END (* IF *);
        RETURN TRUE
      ELSE
        pl := rl;
        rl := rl.tail
      END (* IF *)
    END (* WHILE *);
    RETURN FALSE
  END Delete;

PROCEDURE Size(s: T): CARDINAL =
  BEGIN RETURN ElemList.Length(s.l) END Size;

PROCEDURE Intersection(s1: T; s2: ElemSet.T): ElemSet.T =
  VAR rl1 := s1.l; res := NEW(T).init(); BEGIN
    WHILE rl1 # NIL DO
      IF s2.member(rl1.head) THEN
        res.l := ElemList.Cons(rl1.head, res.l)
      END (* IF *);
      rl1 := rl1.tail
    END (* WHILE *);
    RETURN res
  END Intersection;

PROCEDURE Diff(s1: T; s2: ElemSet.T): ElemSet.T =
  VAR rl1 := s1.l; res := NEW(T).init(); BEGIN
    WHILE rl1 # NIL DO
      IF NOT s2.member(rl1.head) THEN
        res.l := ElemList.Cons(rl1.head, res.l)
      END (* IF *);
      rl1 := rl1.tail
    END (* WHILE *);
    RETURN res
  END Diff;

PROCEDURE IntersectionD(s1: T; s2: ElemSet.T): ElemSet.T =
  VAR prl1: ElemList.T := NIL;
      rl1 := s1.l;
  BEGIN
    WHILE rl1 # NIL DO
      IF NOT s2.member(rl1.head) THEN
        IF prl1 = NIL THEN
          s1.l := rl1.tail
        ELSE
          prl1.tail := rl1.tail
        END (* IF *)
      ELSE
        prl1 := rl1
      END (* IF *);
      rl1 := rl1.tail
    END (* WHILE *);
    RETURN s1
  END IntersectionD;

PROCEDURE DiffD(s1: T; s2: ElemSet.T): ElemSet.T =
  VAR prl1: ElemList.T := NIL;
      rl1 := s1.l;
  BEGIN
    WHILE rl1 # NIL DO
      IF s2.member(rl1.head) THEN
        IF prl1 = NIL THEN
          s1.l := rl1.tail
        ELSE
          prl1.tail := rl1.tail
        END (* IF *)
      ELSE
        prl1 := rl1
      END (* IF *);
      rl1 := rl1.tail
    END (* WHILE *);
    RETURN s1
  END DiffD;

PROCEDURE Iterate(s: T): ElemSet.Iterator =
  VAR res := NEW(Iterator, l := s.l); BEGIN
    RETURN res;
  END Iterate;

PROCEDURE Next(iter: Iterator; VAR e: Elem.T): BOOLEAN =
  BEGIN
    IF iter.l = NIL THEN
      RETURN FALSE
    ELSE
      e := iter.l.head;
      iter.l := iter.l.tail;
      RETURN TRUE
    END (* IF *)
  END Next;

BEGIN
END SetList.