-- Stone 26-Jun-81 15:28:54
-- Cedar version:18-Jun-81 14:24:37
-- Ordered pairs; building and searching
-- Nearly the same as Relations, written by Rick Tiberi

DIRECTORY
	PairList;

PairListImpl: PROGRAM
	EXPORTS PairList =
BEGIN OPEN PairList;

NotFound: PUBLIC SIGNAL = CODE;

CreateRelation: PUBLIC PROCEDURE RETURNS [relation: Relation] =
BEGIN
relation ← NEW[RelationHead];
END;

AddPair: PUBLIC PROCEDURE [relation: Relation,
		left, right: REF ANY] =
BEGIN
pair: REF Pair ← NEW[Pair];
pair.left ← left; pair.right ← right;
pair.link ← relation.first;
relation.first ← pair;
END;

Left: PUBLIC PROCEDURE[relation: Relation, equals: EqualProc, right: REF ANY]
	RETURNS [left: REF ANY] =
BEGIN
notFound: BOOLEAN ← TRUE;
IsRight: PROCEDURE [leftPart, rightPart: REF ANY] =
	BEGIN
	IF equals[right,rightPart] THEN {left←leftPart; notFound← FALSE};
	END;
ForAllPairs[relation, IsRight];
IF notFound THEN SIGNAL NotFound;
END;

Right: PUBLIC PROCEDURE[relation: Relation, equals: EqualProc, left: REF ANY]
	RETURNS [right: REF ANY] =
BEGIN
notFound: BOOLEAN ← TRUE;
IsLeft: PROCEDURE [leftPart, rightPart: REF ANY] =
	BEGIN
	IF equals[left,leftPart] THEN {right←rightPart; notFound← FALSE};
	END;
ForAllPairs[relation, IsLeft];
IF notFound THEN SIGNAL NotFound;
END;

ForAllPairs: PUBLIC PROCEDURE[relation: Relation,
	do: PROCEDURE[leftPart, rightPart: REF ANY]] =
BEGIN
pair: REF Pair ← NIL;
IF relation=NIL THEN RETURN;
FOR pair ← relation.first, pair.link UNTIL pair=NIL
	DO do[pair.left, pair.right] ENDLOOP;
END;

DestroyRelation: PUBLIC PROCEDURE[relation: Relation] =
BEGIN
pair, next: REF Pair ← NIL;
IF relation=NIL THEN RETURN;
FOR pair ← relation.first, next UNTIL pair=NIL
	DO
	next ← pair.link;
	ENDLOOP;
END;

END.