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:
BOOL ←
FALSE];
Enumerates those [i, v] in fn such that i in left and v in right.
Tester: TYPE ~ PROC [pair: IVPair] RETURNS [pass: BOOL ← FALSE];
Scan:
PROC [fn: IntFn,
Test: Tester, left: Interval ← [], right: Collection ← passAll, bkwd:
BOOL ←
FALSE]
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:
BOOL ←
FALSE]
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:
BOOL ←
FALSE]
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:
BOOL ←
FALSE]
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:
BOOL ←
FALSE]
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:
LNAT ←
LNAT.
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: BOOL ← FALSE, right: Space ← refs, invable: BOOL ← FALSE] 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:
BOOL ←
FALSE, 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:
BOOL ←
FALSE, 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:
BOOL ←
FALSE]
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: BOOL ← FALSE, rightSpace: Space ← refs] RETURNS [Array];
CreateRedBlackCopy: PROC [array: Array, bounds: Interval ← [], oneToOne, dense: NewBOOL ← SAME, invable: BOOL ← FALSE, rightSpace: Space ← NIL] RETURNS [Array];
Compose: PROC [left: IntFn, right: Function, leftRestricts, rightRestricts: BOOL ← TRUE] 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: BOOL ← FALSE,
mutability: Mutability ← variable,
domainFixed: BOOL ← FALSE,
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]];
}.