PairCollections.Mesa
Last tweaked by Mike Spreitzer on October 16, 1987 10:03:48 am PDT
DIRECTORY Atom, Basics, Collections;
PairCollections: CEDAR DEFINITIONS
IMPORTS Collections
= {OPEN Colls: Collections, Collections;
Random Old Stuff
Collection: TYPE ~ Colls.Collection;
Value: TYPE ~ Colls.Value;
Direction: TYPE ~ Colls.Direction;
Side: TYPE ~ Colls.Side;
BoolPair: TYPE ~ Colls.BoolPair;
Pairs, and Collections of Them
Pair: TYPE ~ ARRAY Side OF Value;
noPair: READONLY Pair -- = [noValue, noValue] --;
PairColl: TYPE ~ RECORD [class: PairCollClass, data: Value];
A collection of Pairs, or a variable such.
Cons: PROC [class: PairCollClass, data: REF ANY] RETURNS [PairColl];
Good for calling from the interpreter.
nilPairColl: PairColl ~ [NIL, NIL];
DeRef: PROC [ra: REF ANY] RETURNS [PairColl]
~ INLINE {RETURN [IF ra#NIL THEN NARROW[ra, REF PairColl]^ ELSE nilPairColl]};
Refify: PROC [pc: PairColl] RETURNS [ref: REF ANY]
~ INLINE {ref ← NEW [PairColl ← pc]};
Operations on PairColls
Cant: ERROR [pc: PairColl];
Raised when a pair collection is asked to perform an operation it can't.
QualityOf: PROC [pc: PairColl, op: ATOM, args: ArgList ← NIL] RETURNS [ImplQuality];
Use this to investigate what operations a collection supports, and how well it does so. The quality depends on the collection, the operation, and certain arguments. Those arguments are the Direction, or the Side, or the bkwds: BOOL, if any. They are indicated to QualityOf as a LIST OF REF ANY, where each REF ANY is an ATOM whose name is the name of the enumerated value (e.g., $leftToRight, $FALSE). The op is the name of a procedure in this interface (other than QualityOf and derivatives) that calls class procedures.
Can: PROC [pc: PairColl, op: ATOM, args: ArgList ← NIL] RETURNS [BOOL]
~ INLINE {RETURN [QualityOf[pc, op, args]#cant]};
Widen: PROC [pc: PairColl] RETURNS [Collection--of REF Pair--]
~ INLINE {RETURN pc.class.Widen[pc]};
HasPair: PROC [pc: PairColl, pair: Pair] RETURNS [BOOL]
~ INLINE {RETURN pc.class.HasPair[pc, pair]};
OrderStyleOf: PROC [pc: PairColl] RETURNS [OrderStyle]
~ INLINE {RETURN [pc.class.orderStyle]};
Ordering: TYPE ~ RECORD [Compare: PairCompareProc, data: REF ANY, sideCare: SideCare];
PairCompareProc: TYPE ~ PROC [data: REF ANY, elt1, elt2: Pair] RETURNS [Basics.Comparison];
SideCare: TYPE ~ {neither, left, right, both};
unordered: Ordering ~ [NIL, NIL, neither];
OrderBySide: PROC [side: Side, o: Colls.Ordering] RETURNS [Ordering];
OrderByBoth: PROC [highSide: Side, high, low: Colls.Ordering] RETURNS [Ordering];
OrderingOf: PROC [pc: PairColl] RETURNS [Ordering]
~ INLINE {RETURN pc.class.OrderingOf[pc]};
CaresAbout: PROC [sideCare: SideCare, side: Side] RETURNS [BOOL]
~ INLINE {RETURN [SELECT sideCare FROM
neither => FALSE,
left => side=left,
right => side=right,
both => TRUE,
ENDCASE => ERROR]};
Image: PROC [pc: PairColl, coll: Collection, dir: Direction ← leftToRight] RETURNS [UWColl]
For leftToRight, the result is the things that are on the right sides of pairs in pc that have an element of coll on their left side. The result tracks changes to the PairColl, but may not be changed directly.
~ INLINE {RETURN pc.class.Image[pc, coll, dir]};
Mapping: PROC [pc: PairColl, v: Value, dir: Direction ← leftToRight] RETURNS [UWColl]
The image of a singleton.
~ INLINE {RETURN pc.class.Image[pc, Colls.CreateSingleton[v, pc.Spaces[][Source[dir]]], dir]};
Enumerate: PROC [pc: PairColl, Consume: PROC [Pair], bkwd: BOOLFALSE];
MaybePair: TYPE ~ RECORD [found: BOOL, pair: Pair];
noMaybePair: READONLY MaybePair -- = [FALSE, noPair] --;
ParallelFind: TYPE ~ RECORD [found: BOOL, a, b: MaybePair];
Tester: TYPE ~ PROC [pair: Pair] RETURNS [pass: BOOLFALSE];
Scan: PROC [pc: PairColl, Test: Tester, bkwd: BOOLFALSE] RETURNS [MaybePair]
~ INLINE {RETURN pc.class.Scan[pc, Test, bkwd]};
EnumerateImage: PROC [pc: PairColl, coll: Collection, Consume: PROC [Value], dir: Direction ← leftToRight, bkwd: BOOLFALSE];
EnumerateMapping: PROC [pc: PairColl, v: Value, Consume: PROC [Value], dir: Direction ← leftToRight, bkwd: BOOLFALSE]
~ INLINE {EnumerateImage[pc, Colls.CreateSingleton[v, pc.Spaces[][Source[dir]]], Consume, dir, bkwd]};
EnumerateHalfRestriction: PROC [pc: PairColl, coll: Collection, Consume: PROC [Pair], side: Side ← left, bkwd: BOOLFALSE];
Enumerates those pairs such that pair[side] is in coll.
ScanImage: PROC [pc: PairColl, coll: Collection, Test: Colls.Tester, dir: Direction ← leftToRight, bkwd: BOOLFALSE] RETURNS [MaybePair];
ScanMapping: PROC [pc: PairColl, v: Value, Test: Colls.Tester, dir: Direction ← leftToRight, bkwd: BOOLFALSE] RETURNS [MaybePair]
~ INLINE {RETURN ScanImage[pc, Colls.CreateSingleton[v, pc.Spaces[][Source[dir]]], Test, dir, bkwd]};
ScanHalfRestriction: PROC [pc: PairColl, coll: Collection, Test: Tester, side: Side ← left, bkwd: BOOLFALSE] RETURNS [MaybePair]
~ INLINE {RETURN pc.class.ScanHalfRestriction[pc, side, coll, Test, bkwd]};
ParallelTester: TYPE ~ PROC [a, b: MaybePair] RETURNS [pass: BOOLFALSE];
ParallelScan: PROC [a, b: PairColl, Test: ParallelTester, bkwd: BOOLFALSE] RETURNS [ParallelFind]
~ INLINE {RETURN ParallelScanHalfRestriction[a, b, passAll, Test, left, bkwd]};
ParallelScanHalfRestriction: PROC [a, b: PairColl, coll: Collection, Test: ParallelTester, side: Side ← left, bkwd: BOOLFALSE] RETURNS [ParallelFind];
First: PROC [pc: PairColl] RETURNS [MaybePair]
~ INLINE {RETURN pc.class.Extremum[pc, FALSE, FALSE]};
Last: PROC [pc: PairColl] RETURNS [MaybePair]
~ INLINE {RETURN pc.class.Extremum[pc, TRUE, FALSE]};
Pop: PROC [pc: PairColl, bkwd: BOOLFALSE] RETURNS [MaybePair]
~ INLINE {RETURN pc.class.Extremum[pc, bkwd, TRUE]};
Extremum: PROC [pc: PairColl, bkwd, remove: BOOL] RETURNS [MaybePair]
~ INLINE {RETURN pc.class.Extremum[pc, bkwd, remove]};
Next: PROC [pc: PairColl, pair: Pair] RETURNS [MaybePair]
~ INLINE {RETURN [pc.class.Get3[pc, pair].next]};
Prev: PROC [pc: PairColl, pair: Pair] RETURNS [MaybePair]
~ INLINE {RETURN [pc.class.Get3[pc, pair].prev]};
Get3: PROC [pc: PairColl, pair: Pair] RETURNS [prev, same, next: MaybePair]
~ INLINE {RETURN pc.class.Get3[pc, pair]};
Size: PROC [pc: PairColl, limit: LNATLNAT.LAST] RETURNS [LNAT]
~ INLINE {RETURN [pc.class.Size[pc, limit]]};
Empty: PROC [pc: PairColl] RETURNS [BOOL]
~ INLINE {RETURN [pc.class.Size[pc, 1]=0]};
ImageSize: PROC [pc: PairColl, coll: Collection, dir: Direction ← leftToRight, limit: LNATLNAT.LAST] RETURNS [LNAT]
~ INLINE {RETURN [pc.class.ImageSize[pc, coll, dir, limit]]};
MappingSize: PROC [pc: PairColl, v: Value, dir: Direction ← leftToRight, limit: LNATLNAT.LAST] RETURNS [LNAT]
~ INLINE {RETURN [pc.class.ImageSize[pc, Colls.CreateSingleton[v, pc.Spaces[][Source[dir]]], dir, limit]]};
MutabilityOf: PROC [pc: PairColl] RETURNS [Mutability]
~ INLINE {RETURN [pc.class.mutability]};
Copy: PROC [pc: PairColl] RETURNS [VarPairColl]
~ INLINE {RETURN pc.class.Copy[pc]};
Insulate: PROC [pc: PairColl] RETURNS [UWPairColl]
~ INLINE {RETURN pc.class.Insulate[pc]};
ValueOf: PROC [pc: PairColl] RETURNS [ConstPairColl]
~ INLINE {RETURN pc.class.ValueOf[pc]};
Freeze: PROC [pc: PairColl] RETURNS [const: ConstPairColl]
~ INLINE {RETURN pc.class.Freeze[pc]};
Thaw: PROC [pc: PairColl]
~ INLINE {pc.class.Thaw[pc]};
Where: TYPE ~ RECORD [SELECT kind: WhereKind FROM
any => [],
end => [end: End],
rel => [pair: Pair, reln: WhereReln],
ENDCASE ← any[]];
News: TYPE ~ {same, different, new};
NewsPair: TYPE ~ PACKED ARRAY Direction OF News;
NewsSetPair: TYPE ~ ARRAY Direction OF PACKED ARRAY News OF BOOL;
When adding a pair to a variable collection that is Functional[dir], the resultant NewsPair[dir] tells about the previous state of that variable: new means there was previously no pair with equivalent [Source[dir]]; different means there was a pair with equivalent [Source[dir]] and non-equivalent [Dest[dir]]; same means there was previously an equivalent pair. If the collection is not Functional[dir], the resultant NewsPair[dir] can be anything.
IfNews: TYPE ~ PACKED ARRAY --news=new--BOOL OF --add:--BOOL;
IfNewsPair: TYPE ~ ARRAY Direction OF IfNews;
The procedures that add to variable pair collections can be conditional on the previous state: if the collection is Functional[dir], if[dir][news[dir]=new] must be TRUE in order for the addition to happen.
alwaysAdd: IfNewsPair ~ ALL[ALL[TRUE]];
addIfNew: IfNewsPair ~ ALL[[FALSE, TRUE]];
addIfOld: IfNewsPair ~ ALL[[TRUE, FALSE]];
AddPair: PROC [pc: PairColl, pair: Pair, if: IfNewsPair ← alwaysAdd, where: Where ← []] RETURNS [news: NewsPair];
AddNewPair: PROC [pc: PairColl, pair: Pair, where: Where ← []];
Like AddPair, with the expectation that the pair is new.
AddColl: PROC [pc, other: PairColl, if: IfNewsPair ← alwaysAdd, where: Where ← []] RETURNS [some: NewsSetPair]
Equivalent to a series of AddPairs. some[n][dir] iff some AddPair[..][dir]=n.
~ INLINE {RETURN pc.class.AddColl[pc, other, if, where]};
AddNewColl: PROC [pc, other: PairColl, where: Where ← []];
Same as AddColl[if: addIfNew], and then in functional directions d insist that some[d][same] = some[d][different] = FALSE.
RemPair: PROC [pc: PairColl, pair: Pair, style: RemoveStyle ← any] RETURNS [hadMapping: BoolPair]
For collections that are Functional[dir]: hadMapping[dir] tells whether there was a pair with an equivalent Value on the Source[dir] side; for those not functional, hadMapping[dir] is unrestricted.
~ INLINE {RETURN [pc.class.RemColl[pc, CreateSingleton[pair, pc.Spaces[]], style].hadAll]};
RemColl: PROC [pc, other: PairColl, style: RemoveStyle ← any] RETURNS [hadSome, hadAll: BoolPair]
Equivalent to a bunch of RemPairs. hadSome[dir] is the OR of the hadMapping[dir]s, and hadAll[dir] is the AND.
~ INLINE {RETURN pc.class.RemColl[pc, other, style]};
Delete: PROC [pc: PairColl, val: Value, side: Side ← left, style: RemoveStyle ← all] RETURNS [hadSome: BOOL]
Remove pair(s) with equivalent values on the given side. hadSome tells whether there were any.
~ INLINE {RETURN [pc.class.DeleteColl[pc, Colls.CreateSingleton[val, pc.Spaces[][side]], side, style].hadSome]};
DeleteColl: PROC [pc: PairColl, coll: Collection, side: Side ← left, style: RemoveStyle ← all] RETURNS [hadSome, hadAll: BOOL]
~ INLINE {RETURN pc.class.DeleteColl[pc, coll, side, style]};
Spaces: PROC [pc: PairColl] RETURNS [SpacePair]
A PairColl must know the space on either side if it's functional in either direction.
~ INLINE {RETURN pc.class.Spaces[pc]};
CollectionOn: PROC [pc: PairColl, side: Side] RETURNS [UWColl]
Returns a collection of the elements on the given side of the pairs of pc. Result tracks changes to pc.
~ INLINE {RETURN [pc.class.CollectionOn[pc, side]]};
CurSetOn: PROC [pc: PairColl, side: Side] RETURNS [ConstSet]
Returns the current value, and thus does not track changes to pc.
~ INLINE {RETURN [[pc.class.CurSetOn[pc, side]]]};
Functional: PROC [pc: PairColl] RETURNS [BoolPair]
Functional[pc][leftToRight] => pc can't have two pairs with equivalent left Values and non-equivalent right Values.
~ INLINE {RETURN [pc.class.functional]};
MayDuplicate: PROC [pc: PairColl] RETURNS [BOOL]
Might this relation enumerate equivalent pairs (or mappings) more than once?
~ INLINE {RETURN [pc.class.mayDuplicate]};
refPairColls: READONLY Space;
Equal: PROC [a, b: PairColl, bounds: CollPair ← [passAll, passAll]] RETURNS [BOOL];
x in bounds[left], y in bounds[right] : <x,y> in a { <x,y> in b.
Hash: PROC [pc: PairColl, bounds: CollPair ← [passAll, passAll]] RETURNS [CARDINAL];
Compare: PROC [a, b: PairColl, bounds: CollPair ← [passAll, passAll]] RETURNS [Basics.Comparison];
Special Cases of PairColls
VarPairColl: TYPE ~ RECORD [PairColl] --a variable PairColl--;
IsVar: PROC [pc: PairColl] RETURNS [BOOL]
~ INLINE {RETURN [pc.class.mutability=variable]};
AsVar: PROC [pc: PairColl] RETURNS [VarPairColl]
~ INLINE {IF pc#nilPairColl AND pc.class.mutability#variable THEN Complain[pc, notVariable]; RETURN [[pc]]};
UWPairColl: TYPE ~ RECORD [PairColl] --an unwritable PairColl--;
IsUW: PROC [pc: PairColl] RETURNS [BOOL]
~ INLINE {RETURN [pc.class.mutability#variable]};
AsUW: PROC [pc: PairColl] RETURNS [UWPairColl]
~ INLINE {IF pc#nilPairColl AND pc.class.mutability=variable THEN Complain[pc, writeable]; RETURN [[pc]]};
ConstPairColl: TYPE ~ RECORD [UWPairColl] --a constant PairColl--;
IsConst: PROC [pc: PairColl] RETURNS [BOOL]
~ INLINE {RETURN [pc.class.mutability=constant]};
AsConst: PROC [pc: PairColl] RETURNS [ConstPairColl]
~ INLINE {IF pc#nilPairColl AND pc.class.mutability#constant THEN Complain[pc, notConstant]; RETURN [[[pc]]]};
Relation: TYPE ~ PairColl --a binary relation: a non-duplicating pair collection--;
VarRelation: TYPE ~ VarPairColl;
ConstRelation: TYPE ~ ConstPairColl;
IsRelation: PROC [pc: PairColl] RETURNS [BOOL]
~ INLINE {RETURN [NOT pc.class.mayDuplicate]};
Function: TYPE ~ PairColl --a non-duplicating pair collection that doesn't have two pairs with equal left sides--;
VarFunction: TYPE ~ VarPairColl;
UWFunction: TYPE ~ UWPairColl;
ConstFunction: TYPE ~ ConstPairColl;
IsFunction: PROC [pc: PairColl] RETURNS [BOOL]
~ INLINE {RETURN [pc.class.functional[leftToRight] AND NOT pc.class.mayDuplicate]};
InvFunction: TYPE ~ PairColl --a non-duplicating pair collection that doesn't have two pairs with equal right sides--;
VarInvFunction: TYPE ~ VarPairColl;
UWInvFunction: TYPE ~ UWPairColl;
ConstInvFunction: TYPE ~ ConstPairColl;
IsInvFunction: PROC [pc: PairColl] RETURNS [BOOL]
~ INLINE {RETURN [pc.class.functional[rightToLeft] AND NOT pc.class.mayDuplicate]};
OneToOne: TYPE ~ PairColl --a one-to-one relation--;
VarOneToOne: TYPE ~ VarPairColl;
ConstOneToOne: TYPE ~ ConstPairColl;
IsOneToOne: PROC [pc: PairColl] RETURNS [BOOL]
~ INLINE {RETURN [pc.class.functional=ALL[TRUE] AND NOT pc.class.mayDuplicate]};
Store: PROC [pc: Function, pair: Pair] RETURNS [new: BOOL]
~ INLINE {RETURN [pc.AddPair[pair][leftToRight]=new]};
Replace: PROC [pc: Function, pair: Pair] RETURNS [old: BOOL]
~ INLINE {RETURN [pc.AddPair[pair, [[TRUE, FALSE], ALL[TRUE]]][leftToRight]#new]};
Insert: PROC [pc: Function, pair: Pair] RETURNS [new: BOOL]
~ INLINE {RETURN [pc.AddPair[pair, [[FALSE, TRUE], ALL[TRUE]]][leftToRight]=new]};
Inserted: PROC [pc: Function, pair: Pair] RETURNS [Value]
~ INLINE {
IF NOT pc.Insert[pair] THEN Error[notNew, LIST[NEW [Function ← pc], NEW [Pair ← pair]]];
RETURN [pair[right]]};
notNew: READONLY ROPE;
Apply: PROC [pc: PairColl, v: Value, dir: Direction ← leftToRight] RETURNS [MaybeValue]
pc must be Functional[dir]. Returns noMaybe if no such pair.
~ INLINE {RETURN pc.class.Apply[pc, v, dir]};
Bag: TYPE ~ Function --where range is REF INT; this is a.k.a. a multiset; it is a function from an item to the number of occurrences of that item--;
IsIntFn: PROC [pc: PairColl, dir: Direction ← leftToRight] RETURNS [BOOL]
~ INLINE {RETURN [pc.QuaIntFn.found]};
AsIntFn: PROC [pc: PairColl, dir: Direction ← leftToRight] RETURNS [REF ANY]
~ INLINE {RETURN [QuaIntFn[pc].val]};
QuaIntFn: PROC [pc: PairColl, dir: Direction ← leftToRight] RETURNS [MaybeValue]
~ INLINE {RETURN pc.class.QuaIntFn[pc, dir]};
Some Implementations of PairColls
empty, id: READONLY ConstPairColl;
CreateSingleton: PROC [elt: Pair, spaces: SpacePair] RETURNS [ConstPairColl]
~ INLINE {RETURN [[[[GetSingletonClass[spaces], NEW [Pair ← elt]]]]]};
GetSingletonClass: PROC [spaces: SpacePair] RETURNS [PairCollClass];
NCreateSingleton: PROC [elt: Pair, spaces: SpacePair] RETURNS [ConstPairColl];
CreateIDSubset: PROC [Collection] RETURNS [PairColl];
CreateProduct: PROC [CollPair] RETURNS [PairColl];
CreateFromList: PROC [vals: LOP, functional: BoolPair ← [FALSE, FALSE], spaces: SpacePair ← [refs, refs], mayDuplicate: BOOLFALSE] RETURNS [ConstPairColl];
HashFn: TYPE ~ VarFunction;
CreateHashReln: PROC [spaces: SpacePair ← [refs, refs], functional: BoolPair ← [FALSE, FALSE], mappable: BoolPair ← [TRUE, TRUE]] RETURNS [VarPairColl];
(functional[dir] OR mappable[dir]) tells whether the result can Image in direction dir.
CreateHashOTO: PROC [spaces: SpacePair ← [refs, refs]] RETURNS [VarOneToOne]
~ INLINE {RETURN CreateHashReln[spaces, ALL[TRUE]]};
CreateHashFn: PROC [spaces: SpacePair ← [refs, refs], invable: BOOLTRUE] RETURNS [HashFn]
~ INLINE {RETURN CreateHashReln[spaces, [TRUE, FALSE], [TRUE, invable]]};
CreateHashTable: PROC [right: Space ← refs, invable: BOOLTRUE] RETURNS [HashFn]
~ INLINE {RETURN CreateHashReln[[refs, right], [TRUE, FALSE], [TRUE, invable]]};
CreateHashDictionary: PROC [case: BOOLTRUE, right: Space ← refs, invable: BOOLTRUE] RETURNS [HashFn]
~ INLINE {RETURN CreateHashReln[[ropes[case], right], [TRUE, FALSE], [TRUE, invable]]};
CreateHashCopy: PROC [pc: PairColl, spaces: SpacePair ← [NIL, NIL], mappable: BoolPair ← [FALSE, FALSE]] RETURNS [HashFn];
NIL space means use the same space as the given PairColl. Can map in direction d if the orginial can or if mappable[d].
RedBlackReln: TYPE ~ VarRelation;
CreateRedBlackReln: PROC [spaces: SpacePair ← [refs, refs], functional: BoolPair ← [FALSE, FALSE], mappable: BoolPair ← [TRUE, TRUE]] RETURNS [RedBlackReln];
CreateRedBlackCopy: PROC [pc: PairColl, spaces: SpacePair ← [NIL, NIL], mappable: BoolPair ← [FALSE, FALSE]] RETURNS [RedBlackReln];
The following use a standard implementation. The result tracks changes to the arguments, if any. Result may duplicate iff any argument may.
Union: PROC [a, b: PairColl] RETURNS [PairColl];
DisjointUnion: PROC [a, b: Relation] RETURNS [Relation];
Assumes arguments have no elements in common.
Intersection: PROC [PairColl, PairColl] RETURNS [PairColl];
Difference: PROC [PairColl, PairColl] RETURNS [PairColl];
SymmetricDifference: PROC [a, b: PairColl] RETURNS [c: PairColl];
Negate: PROC [PairColl] RETURNS [PairColl];
Compose: PROC [pcs: ARRAY Side OF PairColl, restricts: ARRAY Side OF BOOL ← [TRUE, TRUE]] RETURNS [PairColl];
restricts[side]=FALSE means caller is guaranteeing that henceforth CollectionOn[pcs[OtherSide[side]], side] is included in CollectionOn[pcs[side], OtherSide[side]].
Invert: PROC [PairColl] RETURNS [PairColl];
FnFromProc: PROC [Apply: PROC [data: REF ANY, v: Value] RETURNS [mv: MaybeValue], spaces: SpacePair ← [refs, refs], data: REF ANYNIL, constant, oneToOne: BOOLFALSE, ScanInverse: PROC [data: REF ANY, v: Value, Test: Tester] RETURNS [MaybePair] ← NIL] RETURNS [Function];
CreateCountingBag: PROC [coll: Collection] RETURNS [Bag]
~ INLINE {RETURN [[countingBagClass, NEW [Collection ← coll]]]};
countingBagClass: READONLY PairCollClass;
Implementing PairColls
PairCollClass: TYPE ~ REF PairCollClassPrivate;
PairCollClassPrivate: TYPE ~ MONITORED RECORD [
Primitive: PROC [pc: PairColl, op: ATOM, args: ArgList ← NIL] RETURNS [PrimitiveAnswer] ← NIL,
Widen: PROC [pc: PairColl] RETURNS [Collection--of REF Pair--] ← NIL,
HasPair: PROC [pc: PairColl, pair: Pair] RETURNS [BOOL] ← NIL,
Image: PROC [pc: PairColl, coll: Collection, dir: Direction] RETURNS [UWColl] ← NIL,
Apply: PROC [pc: PairColl, v: Value, dir: Direction] RETURNS [MaybeValue] ← NIL,
Scan: PROC [pc: PairColl, Test: Tester, bkwd: BOOL] RETURNS [MaybePair] ← NIL,
ScanHalfRestriction: PROC [pc: PairColl, side: Side, coll: Collection, Test: Tester, bkwd: BOOL] RETURNS [MaybePair] ← NIL,
Extremum: PROC [pc: PairColl, bkwd, remove: BOOL] RETURNS [MaybePair] ← NIL,
Get3: PROC [pc: PairColl, pair: Pair] RETURNS [prev, same, next: MaybePair] ← NIL,
Size: PROC [pc: PairColl, limit: LNAT] RETURNS [LNAT] ← NIL,
ImageSize: PROC [pc: PairColl, coll: Collection, dir: Direction, limit: LNAT] RETURNS [LNAT] ← NIL,
Copy: PROC [pc: PairColl] RETURNS [VarPairColl] ← NIL,
Insulate: PROC [pc: PairColl] RETURNS [UWPairColl] ← NIL,
ValueOf: PROC [pc: PairColl] RETURNS [ConstPairColl] ← NIL,
Freeze: PROC [pc: PairColl] RETURNS [const: ConstPairColl] ← NIL,
Thaw: PROC [pc: PairColl] ← NIL,
CollectionOn: PROC [pc: PairColl, side: Side] RETURNS [UWColl] ← NIL,
CurSetOn: PROC [pc: PairColl, side: Side] RETURNS [ConstSet] ← NIL,
AddColl: PROC [pc, other: PairColl, if: IfNewsPair, where: Where] RETURNS [some: NewsSetPair] ← NIL,
RemColl: PROC [pc, other: PairColl, style: RemoveStyle] RETURNS [hadSome, hadAll: BoolPair] ← NIL,
DeleteColl: PROC [pc: PairColl, coll: Collection, side: Side, style: RemoveStyle] RETURNS [hadSome, hadAll: BOOL] ← NIL,
QuaIntFn: PROC [pc: PairColl, dir: Direction] RETURNS [MaybeValue] ← NIL,
Spaces: PROC [pc: PairColl] RETURNS [SpacePair] ← NIL,
OrderingOf: PROC [pc: PairColl] RETURNS [Ordering] ← NIL,
functional: BoolPair ← [FALSE, FALSE],
mayDuplicate: BOOLTRUE,
orderStyle: OrderStyle ← none,
mutability: Mutability ← variable,
other: Atom.PropList ← NIL, --the canonical expansion slot
data: Value ← NIL
];
The only part that may vary is the other, and that must be accessed through the update procedure below.
CreateClass:
PROC [cp: PairCollClassPrivate,
bkwdable: BB ← [TRUE, FALSE],
dirable: BoolPair ← [TRUE, FALSE]]
RETURNS [PairCollClass];
NIL procs mean the implementor declines to implement the proc; NIL fields get filled in with default procedures that compute with provided fields. Iff Primitive is elided, `bkwdable' and `dirable' are taken into consideration when constructing Primitive.
DefaultWiden: PROC [pc: PairColl] RETURNS [Collection--of REF Pair--];
DefaultImage: PROC [pc: PairColl, coll: Collection, dir: Direction] RETURNS [UWColl];
DefaultApply: PROC [pc: PairColl, v: Value, dir: Direction] RETURNS [MaybeValue];
DefaultScan: PROC [pc: PairColl, Test: Tester, bkwd: BOOL] RETURNS [MaybePair];
DefaultScanHalfRestriction: PROC [pc: PairColl, side: Side, coll: Collection, Test: Tester, bkwd: BOOL] RETURNS [MaybePair];
DefaultExtremum: PROC [pc: PairColl, bkwd, remove: BOOL] RETURNS [MaybePair];
DefaultGet3: PROC [pc: PairColl, pair: Pair] RETURNS [prev, same, next: MaybePair];
DefaultImageSize: PROC [pc: PairColl, coll: Collection, dir: Direction, limit: LNAT] RETURNS [LNAT];
DefaultCollectionOn: PROC [pc: PairColl, side: Side] RETURNS [UWColl];
DefaultCurSetOn: PROC [pc: PairColl, side: Side] RETURNS [ConstSet];
DefaultInsulate: PROC [pc: PairColl] RETURNS [UWPairColl];
DefaultDeleteColl: PROC [pc: PairColl, coll: Collection, side: Side, style: RemoveStyle] RETURNS [hadSome, hadAll: BOOL];
DefaultQuaIntFn: PROC [pc: PairColl, dir: Direction] RETURNS [MaybeValue];
DefaultSpaces: PROC [pc: PairColl] RETURNS [SpacePair];
DefaultOrderingOf: PROC [pc: PairColl] RETURNS [Ordering];
IsDefaultOrdering: PROC [Ordering] RETURNS [BOOL];
GetSide: PROC [args: ArgList, i: NAT, default: Side ← left] RETURNS [Side];
FromSide: PROC [Side] RETURNS [ATOM];
UpdatePairCollClassOther: PROC [class: PairCollClass, Update: PROC [Atom.PropList] RETURNS [Atom.PropList]];
Other Random New Stuff
InvertSideCare: ARRAY SideCare OF SideCare
~ [neither: neither, left: right, right: left, both: both];
SpacePair: TYPE ~ ARRAY Side OF Space;
LOP: TYPE ~ LIST OF Pair;
CollPair: TYPE ~ ARRAY Side OF Collection;
ConsPair: PROC [first: Side, v1, v2: Value] RETURNS [pair: Pair]
~ INLINE {pair[first] ← v1; pair[OtherSide[first]] ← v2};
Complain: PROC [pc: PairColl, msg: ROPE, args: LOVNIL]
~ INLINE {Error[msg, CONS[NEW [PairColl ← pc], args]]};
P: PROC [mp: MaybePair] RETURNS [Pair]
~ INLINE {IF mp.found THEN RETURN [mp.pair] ELSE Error[notFound, NIL]};
DP: PROC [mp: MaybePair, ifNotFound: Pair ← [NIL, NIL]] RETURNS [Pair]
~ INLINE {RETURN [IF mp.found THEN mp.pair ELSE ifNotFound]};
WidenSpacePair: PROC [sp: SpacePair] RETURNS [s: Space];
s is a space of REF Pair, where [left] is in sp[left] and [right] is in sp[right].
IsPairSpace: PROC [s: Space] RETURNS [BOOL];
Is s the result of WidenSpacePair?
NarrowSpace: PROC [s: Space] RETURNS [sp: SpacePair];
Please apply only if IsPairSpace[s].
WidenOrdering: PROC [o: Ordering] RETURNS [wo: Colls.Ordering];
wo gives the same order to REF Pairs as o gives to their referents.
NarrowOrdering: PROC [wo: Colls.Ordering] RETURNS [o: Ordering];
wo gives the same order to REF Pairs as o gives to their referents.
InvertPair: PROC [x: Pair] RETURNS [Pair]
Swap [left] and [right].
~ INLINE {RETURN [[x[right], x[left]]]};
InvertBoolPair: PROC [x: BoolPair] RETURNS [BoolPair]
~ INLINE {RETURN [[x[rightToLeft], x[leftToRight]]]};
InvertMaybe: PROC [mp: MaybePair] RETURNS [MaybePair]
~ INLINE {RETURN [[mp.found, InvertPair[mp.pair]]]};
InvertNewsPair: PROC [x: NewsPair] RETURNS [NewsPair]
~ INLINE {RETURN [[x[rightToLeft], x[leftToRight]]]};
InvertNewsSetPair: PROC [x: NewsSetPair] RETURNS [NewsSetPair]
~ INLINE {RETURN [[x[rightToLeft], x[leftToRight]]]};
InvertIfNewsPair: PROC [x: IfNewsPair] RETURNS [IfNewsPair]
~ INLINE {RETURN [[x[rightToLeft], x[leftToRight]]]};
InvertSpacePair: PROC [x: SpacePair] RETURNS [SpacePair]
~ INLINE {RETURN [[x[right], x[left]]]};
InvertWhere: PROC [x: Where] RETURNS [Where]
~ INLINE {WITH x SELECT FROM
y: any Where => RETURN [y];
y: end Where => RETURN [y];
y: rel Where => RETURN [[rel[InvertPair[y.pair], y.reln]]];
ENDCASE => ERROR};
InvertOrdering: PROC [o: Ordering] RETURNS [io: Ordering];
o relates [a1, a2] to [b1, b2] as io relates [a2, a1] to [b2, b1].
ReverseOrdering: PROC [o: Ordering] RETURNS [ro: Ordering];
If o says a before b, ro says b before a.
}.