IntFunctions.Mesa
Last tweaked by Mike Spreitzer on October 16, 1987 10:11:28 am PDT
DIRECTORY Atom, Basics, Collections, IntStuff, PairCollections;
IntFunctions: CEDAR DEFINITIONS
IMPORTS Collections, IntStuff, PairCollections
= {OPEN Colls:Collections, Collections, PairColls:PairCollections, PairCollections, Ints:IntStuff, IntStuff;
Basic Types
EINT: TYPE ~ Ints.EINT;
Interval: TYPE ~ Ints.Interval;
XForm: TYPE ~ Ints.XForm;
IVPair: TYPE ~ RECORD [left: INT, right: Value];
noPair: READONLY IVPair -- = ["this interface makes no attempt to define an exceptional INT, so there's nothing good to put here, and I'm not telling you what's actually used", noValue] --;
IntFn: TYPE ~ RECORD [class: IntFnClass, data: Value];
A function from INT to Value, or a variable function from INT to Value.
nilIntFn: IntFn ~ [NIL, NIL];
DeRef: PROC [ra: REF ANY] RETURNS [IntFn]
~ INLINE {RETURN [IF ra#NIL THEN NARROW[ra, REF IntFn]^ ELSE nilIntFn]};
Refify: PROC [fn: IntFn] RETURNS [ref: REF ANY]
~ INLINE {ref ← NEW [IntFn ← fn]};
MaybeInt: TYPE ~ RECORD [found: BOOL, i: INT];
noInt: READONLY MaybeInt;
I: PROC [m: MaybeInt] RETURNS [INT]
~ INLINE {RETURN [IF m.found THEN m.i ELSE Error[notFound, NIL]]};
MaybePair: TYPE ~ RECORD [found: BOOL, pair: IVPair];
noMaybePair: READONLY MaybePair -- = [FALSE, noPair]--;
DropVal: PROC [mp: MaybePair] RETURNS [MaybeInt]
~ INLINE {RETURN [[mp.found, mp.pair.left]]};
DropKey: PROC [mp: MaybePair] RETURNS [MaybeValue]
~ INLINE {RETURN [[mp.found, mp.pair.right]]};
P: PROC [mp: MaybePair] RETURNS [IVPair]
~ INLINE {RETURN [IF mp.found THEN mp.pair ELSE Error[notFound, NIL]]};
DP: PROC [mp: MaybePair, ifNotFound: IVPair ← [INT.FIRST, NIL]] RETURNS [IVPair]
~ INLINE {RETURN [IF mp.found THEN mp.pair ELSE ifNotFound]};
Operations on IntFns
Cant: ERROR [fn: IntFn];
Raised when an IntFn is asked to perform an operation it can't.
QualityOf: PROC [fn: IntFn, op: ATOM, args: ArgList ← NIL] RETURNS [ImplQuality];
The only arguments that make a difference are bkwd: BOOL and restrictions. A restriction is an interval or collection that is to limit the pairs under consideration.
Restriction: TYPE ~ {unrestricted, filtered, restricted, tiny};
unrestricted corresponds to the full interval ([]) or the universal set (passAll). filtered corresponds to a collection that can test membership, but not enumerate. restricted corresponds to a non-full interval or a collection that can enumerate. tiny corresponds to an interval whose length is 0 or 1, or a collection that can enumerate with 0 or 1 elements.
FromRestriction: PROC [Restriction] RETURNS [ATOM];
GetRestriction: PROC [args: ArgList, i: NAT, default: Restriction ← unrestricted] RETURNS [Restriction];
Can: PROC [fn: IntFn, op: ATOM, args: ArgList ← NIL] RETURNS [BOOL]
~ INLINE {RETURN [QualityOf[fn, op, args]#cant]};
Widen: PROC [fn: IntFn] RETURNS [Function--[left]: REF INT--]
~ INLINE {RETURN fn.class.Widen[fn]};
HasPair: PROC [fn: IntFn, pair: IVPair] RETURNS [BOOL]
~ INLINE {RETURN fn.class.HasPair[fn, pair]};
Apply: PROC [fn: IntFn, i: INT] RETURNS [MaybeValue]
~ INLINE {RETURN fn.class.Apply[fn, i]};
InvApply: PROC [fn: IntFn, v: Value] RETURNS [MaybeInt]
fn must be one-to-one.
~ INLINE {RETURN fn.class.InvApply[fn, v]};
Ordered: PROC [fn: IntFn] RETURNS [BOOL]
An ordered IntFn's forward enumeration order is increasing left side. No guarantees about an unordered one.
~ INLINE {RETURN [fn.class.ordered]};
Enumerate: PROC [fn: IntFn, Consume: PROC [IVPair], left: Interval ← [], right: Collection ← passAll, bkwd: BOOLFALSE];
Enumerates those [i, v] in fn such that i in left and v in right.
Tester: TYPE ~ PROC [pair: IVPair] RETURNS [pass: BOOLFALSE];
Scan: PROC [fn: IntFn, Test: Tester, left: Interval ← [], right: Collection ← passAll, bkwd: BOOLFALSE] RETURNS [MaybePair]
~ INLINE {RETURN fn.class.Scan[fn, Test, left, right, bkwd]};
First: PROC [fn: IntFn] RETURNS [MaybePair]
~ INLINE {RETURN fn.class.Extremum[fn, FALSE, FALSE]};
Last: PROC [fn: IntFn] RETURNS [MaybePair]
~ INLINE {RETURN fn.class.Extremum[fn, TRUE, FALSE]};
Pop: PROC [fn: IntFn, bkwd: BOOLFALSE] RETURNS [MaybePair]
~ INLINE {RETURN fn.class.Extremum[fn, bkwd, TRUE]};
Extremum: PROC [fn: IntFn, bkwd, remove: BOOL] RETURNS [MaybePair]
~ INLINE {RETURN fn.class.Extremum[fn, bkwd, remove]};
Next: PROC [fn: IntFn, pair: IVPair] RETURNS [MaybePair]
~ INLINE {RETURN [fn.class.Get3[fn, pair].next]};
Prev: PROC [fn: IntFn, pair: IVPair] RETURNS [MaybePair]
~ INLINE {RETURN [fn.class.Get3[fn, pair].prev]};
Get3: PROC [fn: IntFn, pair: IVPair] RETURNS [prev, same, next: MaybePair]
~ INLINE {RETURN fn.class.Get3[fn, pair]};
Index: PROC [fn, goal: IntFn, bounds: Interval ← [], bkwd: BOOLFALSE] RETURNS [MaybeInt]
result is (if bkwd then greatest else least) solution in bounds to: Equal[Shift[fn, -result.i], goal, goal.bounds] (or, equivelently, Equal[fn, Shift[goal, result.i], ShiftInterval[goal.Bounds, resulti]]); if no such solution, result.found=FALSE and result.i is unrestricted.
~ INLINE {RETURN fn.class.Index[fn, goal, bounds, bkwd]};
SkipTo: PROC [fn: IntFn, goal: Collection, bounds: Interval ← [], bkwd: BOOLFALSE] RETURNS [MaybePair]
result is (if bkwd then greatest else least) solution in bounds to: fn[i]=v AND goal.HasMember[v]; if no such solution, result.found=FALSE and result.i is unrestricted.
~ INLINE {RETURN fn.class.Scan[fn, AcceptAny, bounds, goal, bkwd]};
AcceptAny: Tester--={RETURN[TRUE]}--;
Lookup: PROC [fn: IntFn, val: Value, bounds: Interval ← [], bkwd: BOOLFALSE] RETURNS [MaybeInt]
Returns (if bkwd then greatest else least) i in bounds such that fn[i]=val.
~ INLINE {RETURN SkipTo[fn, Colls.CreateSingleton[val, fn.RightSpace], bounds, bkwd].DropVal[]};
~ INLINE {RETURN fn.class.Index[fn, CreateZeroid[val, fn.RightSpace], bounds, bkwd]};
Size: PROC [fn: IntFn, left: Interval ← [], right: Collection ← passAll, limit: LNATLNAT.LAST] RETURNS [LNAT]
~ INLINE {RETURN [fn.class.Size[fn, left, right, limit]]};
Empty: PROC [fn: IntFn] RETURNS [BOOL]
~ INLINE {RETURN [Size[fn: fn, limit: 1]=0]};
GetBounds: PROC [fn: IntFn] RETURNS [Interval]
~ INLINE {RETURN fn.class.GetBounds[fn]};
ImproveBounds: PROC [fn: IntFn, bounds: Interval] RETURNS [Interval]
result.min >= bounds.min. for all i in result.min > i >= bounds.min: i not in domain of fn. result.max has the complementary condition. Thus, if the actual domain is difficult to determine, the given bounds may be returned.
~ INLINE {RETURN fn.class.ImproveBounds[fn, bounds]};
MutabilityOf: PROC [fn: IntFn] RETURNS [Mutability]
~ INLINE {RETURN [fn.class.mutability]};
Copy: PROC [fn: IntFn] RETURNS [VarIntFn]
~ INLINE {RETURN fn.class.Copy[fn]};
Insulate: PROC [fn: IntFn] RETURNS [UWIntFn]
~ INLINE {RETURN fn.class.Insulate[fn]};
ValueOf: PROC [fn: IntFn] RETURNS [ConstIntFn]
~ INLINE {RETURN fn.class.ValueOf[fn]};
Freeze: PROC [fn: IntFn] RETURNS [const: ConstIntFn]
~ INLINE {RETURN fn.class.Freeze[fn]};
Thaw: PROC [fn: IntFn]
~ INLINE {fn.class.Thaw[fn]};
AddPair: PROC [fn: IntFn, pair: IVPair, if: IfNewsPair ← alwaysAdd] RETURNS [news: NewsPair];
Store: PROC [fn: IntFn, pair: IVPair] RETURNS [new: BOOL]
~ INLINE {RETURN [AddPair[fn, pair][leftToRight]=new]};
AddColl: PROC [self, other: IntFn, if: IfNewsPair ← alwaysAdd] RETURNS [some: NewsSetPair]
~ INLINE {RETURN self.class.AddColl[self, other, if]};
RemPair: PROC [fn: IntFn, pair: IVPair] RETURNS [hadMapping: BoolPair]
~ INLINE {RETURN [fn.class.RemColl[fn, CreateSingleton[pair, fn.RightSpace]].hadAll]};
RemColl: PROC [self, other: IntFn] RETURNS [hadSome, hadAll: BoolPair]
~ INLINE {RETURN self.class.RemColl[self, other]};
LeftDelete: PROC [fn: IntFn, int: INT] RETURNS [had: BOOL]
~ INLINE {had ← fn.class.ReplaceMe[fn, empty, [int, int], [int, int]].losses.Positive};
LeftDeleteInterval: PROC [fn: IntFn, interval: Interval] RETURNS [hadSome, hadAll: BOOL]
~ INLINE {
ilen: EINT ~ interval.Length;
losses: EINT ~ fn.class.ReplaceMe[fn, empty, interval, interval].losses;
RETURN [losses.Positive, ilen=losses]};
RightDelete: PROC [fn: IntFn, val: Value, style: RemoveStyle ← all] RETURNS [hadSome: BOOL]
~ INLINE {RETURN [RightDeleteColl[fn, Colls.CreateSingleton[val, fn.RightSpace], style].hadSome]};
RightDeleteColl: PROC [fn: IntFn, coll: Collection, style: RemoveStyle ← all] RETURNS [hadSome, hadAll: BOOL]
~ INLINE {RETURN fn.class.RightDeleteColl[fn, coll, style]};
ReplaceMe: PROC [fn, with: IntFn, where: Interval, clip: Interval] RETURNS [losses, gains: EINT]
new[i, v] iff
old[i, v] & i < where.min, or
with[i-where.min+clip.min, v] & where.min <= i < where.min+clip.Length, or
old[i-clip.Length+where.Length, v] & where.min+clip.Length <= i.
losses = size of intersection of domain of fn and where.
gains = size of intersection of domain of with and clip.
~ INLINE {RETURN fn.class.ReplaceMe[fn, with, where, clip]};
Insert: PROC [fn: IntFn, val: Value, before: INT]
~ INLINE {[] ← ReplaceMe[fn, CreateZeroid[val, fn.RightSpace], [before, before-1], [0, 0]]};
Append: PROC [fn: IntFn, val: Value]
~ INLINE {Insert[fn, val, fn.GetBounds[].max+1]};
Remove: PROC [fn: IntFn, dom: Interval]
~ INLINE {[] ← ReplaceMe[fn, fn, dom, anEmptyInterval]};
ReshapeMe: PROC [fn: IntFn, lt: XForm ← [], lb: Interval ← [], rt: OneToOne ← PairColls.id, rb: Collection ← passAll]
new.HasPair[[lt.XFormInt[i], rt.Apply[v].Val]] iff (old.HasPair[[i, v]] AND i in lb AND v in rb)
~ INLINE {fn.class.ReshapeMe[fn, lt, lb, rt, rb]};
Swap: PROC [fn: IntFn, i, j: INT]
new.HasPair[[i, v]] iff old.HasPair[[j, v]].
new.HasPair[[j, v]] iff old.HasPair[[i, v]].
~ INLINE {fn.class.Swap[fn, i, j]};
RightSpace: PROC [fn: IntFn] RETURNS [Space]
~ INLINE {RETURN fn.class.RightSpace[fn]};
RightCollection: PROC [fn: IntFn] RETURNS [UWColl]
Result tracks changes to fn, if any.
~ INLINE {RETURN fn.class.RightCollection[fn]};
CurRange: PROC [fn: IntFn] RETURNS [ConstSet]
Result does not track changes to fn.
~ INLINE {RETURN fn.class.CurRange[fn]};
IsOneToOne: PROC [fn: IntFn] RETURNS [BOOL]
= Functional[fn.Widen, rightToLeft]
~ INLINE {RETURN [fn.class.isOneToOne]};
DomainIsFixed: PROC [fn: IntFn] RETURNS [BOOL]
A variable IntFn may guarantee that its domain never changes.
~ INLINE {RETURN [fn.class.domainFixed OR fn.class.mutability=constant]};
fixedDomain: READONLY ROPE;
DomainIsDense: PROC [fn: IntFn] RETURNS [BOOL]
Is the domain an interval?
~ INLINE {RETURN [fn.class.isDense]};
refIntFns: READONLY Space;
Equal: PROC [a, b: IntFn, bounds: Interval ← []] RETURNS [BOOL];
a's right Space is used. Only pairs within the given bounds are compared.
Hash: PROC [fn: IntFn, bounds: Interval ← []] RETURNS [CARDINAL];
Compare: PROC [a, b: IntFn, bounds: Interval ← []] RETURNS [Basics.Comparison];
Lexicographic ordering, using a's right space. noValue is considered less than any value. Only pairs within the given bounds are compared.
Special Cases of IntFns
VarIntFn: TYPE ~ RECORD [IntFn] --a variable IntFn--;
IsVar: PROC [fn: IntFn] RETURNS [BOOL]
~ INLINE {RETURN [fn.class.mutability=variable]};
AsVar: PROC [fn: IntFn] RETURNS [VarIntFn]
~ INLINE {RETURN [IF fn.class.mutability=variable THEN [fn] ELSE Cant[fn]]};
UWIntFn: TYPE ~ RECORD [IntFn] --an unwritable IntFn--;
IsUW: PROC [fn: IntFn] RETURNS [BOOL]
~ INLINE {RETURN [fn.class.mutability#variable]};
AsUW: PROC [fn: IntFn] RETURNS [UWIntFn]
~ INLINE {RETURN [IF fn.class.mutability#variable THEN [fn] ELSE Cant[fn]]};
ConstIntFn: TYPE ~ RECORD [UWIntFn] --a constant IntFn--;
IsConst: PROC [fn: IntFn] RETURNS [BOOL]
~ INLINE {RETURN [fn.class.mutability=constant]};
AsConst: PROC [fn: IntFn] RETURNS [ConstIntFn]
~ INLINE {RETURN [IF fn.class.mutability=constant THEN [[fn]] ELSE Cant[fn]]};
Array: TYPE ~ IntFn --whose domain is an interval--;
IsArray: PROC [fn: IntFn] RETURNS [BOOL]
~ INLINE {RETURN [fn.class.isDense]};
FixedArray: TYPE ~ IntFn --whose domain in an unchanging interval--;
IsFixedArray: PROC [fn: IntFn] RETURNS [BOOL]
~ INLINE {RETURN [fn.class.isDense AND (fn.class.mutability=constant OR fn.class.domainFixed)]};
Sequence: TYPE ~ Array --whose lower bound is 0--;
IsSequence: PROC [fn: IntFn] RETURNS [BOOL]
~ INLINE {RETURN [fn.class.isDense AND GetBounds[fn].min=0]};
FixedSequence: TYPE ~ IntFn --a FixedArray whose lower bound is 0--;
IsFixedSequence: PROC [fn: IntFn] RETURNS [BOOL]
~ INLINE {RETURN [fn.class.isDense AND GetBounds[fn].min=0 AND (fn.class.mutability=constant OR fn.class.domainFixed)]};
IsIdentitySubset: PROC [fn: IntFn] RETURNS [BOOL];
TRUE iff for all i in domain of fn: fn[i]=i.
Permutation: TYPE ~ Sequence--new index é old index--;
GradeUp: PROC [a: IntFn, o: Colls.Ordering] RETURNS [p: Permutation];
i < j Ò a[p[i]] d a[p[j]].
TransPermute: PROC [from: IntFn, to: Sequence, p: Permutation];
for each [new, old] in p: to[new] ← from[old].
PermuteInPlace: PROC [a: Sequence, p: Permutation];
Some Implementations of IntFns
empty, id: READONLY ConstIntFn;
The following use a standard implementation. The result tracks changes to the arguments, if any. Result may duplicate iff any argument may.
DisjointUnion: PROC [IntFn, IntFn] RETURNS [IntFn];
Assumes arguments have no elements in common.
Intersection: PROC [IntFn, IntFn] RETURNS [IntFn];
Difference: PROC [IntFn, IntFn] RETURNS [IntFn];
Negate: PROC [IntFn] RETURNS [PairColl];
CreateZeroid: PROC [val: Value, space: Space] RETURNS [ConstIntFn]
Returns a constant IntFn whose domain is {0} and range is {val}.
~ INLINE {RETURN CreateSingleton[[0, val], space]};
CreateSingleton: PROC [pair: IVPair, right: Space] RETURNS [ConstIntFn];
CreateFromList: PROC [vals: LOP, oneToOne: BOOLFALSE, right: Space ← refs, invable: BOOLFALSE] RETURNS [ConstIntFn];
CreateConstant: PROC [bounds: Interval, val: Value, space: Space] RETURNS [ConstIntFn];
Returns a constant IntFn whose domain is bounds and range is {val}.
CreateSimple: PROC [bounds: Interval ← [0, -1], val: Value ← noValue, oneToOne, dense, domainFixed, invable: BOOLFALSE, rightSpace: Space ← refs] RETURNS [Array];
The implementation of this keeps a Cedar SEQUENCE at least long enough to cover the current bounds. Initially allocates a sequence long enough to keep the given bounds. Initially has pairs iff val#noValue, in which case they all have [right]=val and [left] in bounds. If oneToOne, client promises to never require the implicit removal of pairs.
CreateSimpleCopy: PROC [array: Array, bounds: Interval ← [], oneToOne, dense, domainFixed: NewBOOL ← SAME, invable: BOOLFALSE, rightSpace: Space ← NIL] RETURNS [Array];
Like CreateSimple, but the array is initialized from the given array, subject to the given bounds. Giving rightSpace=NIL means to use the original's.
NewBOOL: TYPE ~ {SAME, OPPOSITE, FALSE, TRUE};
UpdateBool: PROC [nb: NewBOOL, b: BOOL] RETURNS [BOOL]
~ INLINE {RETURN [SELECT nb FROM
SAME => b,
OPPOSITE => NOT b,
FALSE => FALSE,
TRUE => TRUE,
ENDCASE => ERROR]};
ConstNew: ARRAY BOOL OF NewBOOL
~ [FALSE: FALSE, TRUE: TRUE];
CreateFromCollection: PROC [coll: Collection, bkwd: BOOLFALSE] RETURNS [Sequence];
[i, v] if v is the i'th element of coll.Enumerate[bkwd]
CreateFromProc: PROC [Produce: PROC [Consume: PROC [val: Value ← noValue, len: LNAT ← 1]], min: INT ← 0] RETURNS [ConstIntFn];
Creates a constant IntFn from a producer of runs.
CollectInterval: PROC [Interval] RETURNS [ConstSet];
CreatePartnership: PROC [a, b: IntFn] RETURNS [IntFn];
a and b cooperate to implement the same function. a provides most of the functionality; b provides backward mapping.
CreateRedBlackArray: PROC [oneToOne, dense, invable: BOOLFALSE, rightSpace: Space ← refs] RETURNS [Array];
CreateRedBlackCopy: PROC [array: Array, bounds: Interval ← [], oneToOne, dense: NewBOOL ← SAME, invable: BOOLFALSE, rightSpace: Space ← NIL] RETURNS [Array];
Compose: PROC [left: IntFn, right: Function, leftRestricts, rightRestricts: BOOLTRUE] RETURNS [IntFn];
Invert: PROC [IntFn] RETURNS [Relation];
Replace: PROC [fn, with: IntFn, where: Interval, clip: Interval] RETURNS [IntFn];
Reshape: PROC [fn: IntFn, lt: XForm ← [], lb: Interval ← [], rt: OneToOne ← PairColls.id, rb: Collection ← passAll] RETURNS [IntFn];
Shift: PROC [fn: IntFn, d: EINT] RETURNS [IntFn]
~ INLINE {RETURN Reshape[fn, [d]]};
Concat: PROC [fn, rest: IntFn] RETURNS [IntFn];
Clip: PROC [fn: IntFn, bounds: Interval ← []] RETURNS [IntFn]
~ INLINE {RETURN Reshape[fn, [], bounds]};
Subseq: PROC [fn: IntFn, bounds: Interval ← []] RETURNS [IntFn]
~ INLINE {RETURN Reshape[fn, [IE[bounds.min].Neg], bounds]};
Implementing IntFns
IntFnClass: TYPE ~ REF IntFnClassPrivate;
IntFnClassPrivate: TYPE ~ MONITORED RECORD [
Primitive: PROC [fn: IntFn, op: ATOM, args: ArgList ← NIL] RETURNS [PrimitiveAnswer] ← NIL,
Widen: PROC [fn: IntFn] RETURNS [Function--[left]: REF INT--] ← NIL,
HasPair: PROC [fn: IntFn, pair: IVPair] RETURNS [BOOL] ← NIL,
Apply: PROC [fn: IntFn, i: INT] RETURNS [MaybeValue] ← NIL,
InvApply: PROC [fn: IntFn, v: Value] RETURNS [MaybeInt] ← NIL,
Scan: PROC [fn: IntFn, Test: Tester, left: Interval, right: Collection, bkwd: BOOL] RETURNS [MaybePair] ← NIL,
Extremum: PROC [fn: IntFn, bkwd, remove: BOOL] RETURNS [MaybePair] ← NIL,
Get3: PROC [fn: IntFn, pair: IVPair] RETURNS [prev, same, next: MaybePair] ← NIL,
Index: PROC [fn, goal: IntFn, bounds: Interval, bkwd: BOOL] RETURNS [MaybeInt] ← NIL,
Size: PROC [fn: IntFn, left: Interval, right: Collection, limit: LNAT] RETURNS [LNAT] ← NIL,
GetBounds: PROC [fn: IntFn] RETURNS [Interval] ← NIL,
ImproveBounds: PROC [fn: IntFn, bounds: Interval] RETURNS [Interval] ← NIL,
Copy: PROC [fn: IntFn] RETURNS [VarIntFn] ← NIL,
Insulate: PROC [fn: IntFn] RETURNS [UWIntFn] ← NIL,
ValueOf: PROC [fn: IntFn] RETURNS [ConstIntFn] ← NIL,
Freeze: PROC [fn: IntFn] RETURNS [const: ConstIntFn] ← NIL,
Thaw: PROC [fn: IntFn] ← NIL,
AddColl: PROC [fn, other: IntFn, if: IfNewsPair] RETURNS [some: NewsSetPair] ← NIL,
RemColl: PROC [fn, other: IntFn] RETURNS [hadSome, hadAll: BoolPair] ← NIL,
RightDeleteColl: PROC [fn: IntFn, coll: Collection, style: RemoveStyle] RETURNS [hadSome, hadAll: BOOL] ← NIL,
ReplaceMe: PROC [fn, with: IntFn, where, clip: Interval] RETURNS [losses, gains: EINT] ← NIL,
ReshapeMe: PROC [fn: IntFn, lt: XForm, lb: Interval, rt: OneToOne, rb: Collection] ← NIL,
Swap: PROC [fn: IntFn, i, j: INT] ← NIL,
RightCollection: PROC [fn: IntFn] RETURNS [UWColl] ← NIL,
CurRange: PROC [fn: IntFn] RETURNS [ConstSet] ← NIL,
RightSpace: PROC [fn: IntFn] RETURNS [Space] ← NIL,
isOneToOne, isDense, ordered: BOOLFALSE,
mutability: Mutability ← variable,
domainFixed: BOOLFALSE,
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: IntFnClassPrivate,
bkwdable: BB ← [TRUE, FALSE]
]
RETURNS [IntFnClass];
NIL procs mean the implementor declines to implement the proc. Where possible, NIL fields get filled in with default procedures that compute with provided fields; the other fields get filled in with CantXXX procedures, which raise Cant.
DefaultWiden: PROC [fn: IntFn] RETURNS [Function--[left]: REF INT--];
DefaultScan: PROC [fn: IntFn, Test: Tester, left: Interval, right: Collection, bkwd: BOOL] RETURNS [MaybePair];
DefaultExtremum: PROC [fn: IntFn, bkwd, remove: BOOL] RETURNS [MaybePair];
DefaultIndex: PROC [fn, goal: IntFn, bounds: Interval, bkwd: BOOL] RETURNS [MaybeInt];
DefaultSize: PROC [fn: IntFn, left: Interval, right: Collection, limit: LNAT] RETURNS [LNAT];
DefaultInsulate: PROC [fn: IntFn] RETURNS [UWIntFn];
DefaultReshapeMe: PROC [fn: IntFn, lt: XForm, lb: Interval, rt: OneToOne, rb: Collection];
UpdateIntFnClassOther: PROC [class: IntFnClass, Update: PROC [Atom.PropList] RETURNS [Atom.PropList]];
Other New Stuff
LOP: TYPE ~ LIST OF IVPair;
Complain: PROC [fn: IntFn, msg: ROPE, args: LOVNIL]
~ INLINE {Error[msg, CONS[NEW [IntFn ← fn], args]]};
}.