Part 1: Basic operations and definitions
RopePart:
TYPE ~
RECORD [base:
ROPE, start, len:
NAT];
0 <= start <= start+len <= base.Length.
No guarantees about what the following procedures do with a broken RopePart.
ROPE: TYPE = Rope.ROPE;
nil: RopePart ~ [NIL, 0, 0]; --one of the possible representations of the empty sequence
MaxLen: INT ~ Rope.MaxLen;
Make:
PROC [base:
ROPE, start:
INT ← 0, len:
INT ← MaxLen]
RETURNS [RopePart];
Returns a RopePart that represents the same sequence as Rope.Substr[base, start, len].
InlineMake:
PROC [base:
ROPE, start:
INT ← 0, len:
INT ← MaxLen]
RETURNS [RopePart]
~
INLINE {limit:
INT ~ base.Length[];
IF start>limit THEN RETURN [nil];
RETURN [[base, start, MIN[len, limit-start]]]};
FromChar:
PROC [
CHAR]
RETURNS [RopePart];
ToRope: PROC [RopePart] RETURNS [ROPE];
InlineToRope:
PROC [rp: RopePart]
RETURNS [
ROPE]
~ INLINE {RETURN rp.base.Substr[start: rp.start, len: rp.len]};
Simplify:
PROC [rp: RopePart, start, end:
BOOL ←
TRUE]
RETURNS [RopePart];
start => result.start = 0.
end => result.start+result.len = result.base.Length.
Cat:
PROC [r1, r2, r3, r4, r5: RopePart ← nil]
RETURNS [RopePart];
Concat:
PROC [base, rest: RopePart ← nil]
RETURNS [RopePart];
EasyConcat:
PROC [base, rest: RopePart ← nil]
RETURNS [
BOOL, RopePart];
Returns [TRUE, concatenation] if it can be done without allocating; otherwise, returns [FALSE, nil].
Compare:
PROC [s1, s2: RopePart, case:
BOOL ←
TRUE]
RETURNS [Basics.Comparison];
Equal:
PROC [s1, s2: RopePart, case:
BOOL ←
TRUE]
RETURNS [
BOOL];
EqualToRope: PROC [s1: RopePart, s2: ROPE, case: BOOL ← TRUE] RETURNS [BOOL];
Fetch:
PROC [base: RopePart, index:
INT ← 0]
RETURNS [c:
CHAR];
InlineFetch:
PROC [base: RopePart, index:
INT]
RETURNS [c:
CHAR]
~ INLINE {RETURN base.base.Fetch[base.start+index]};
Index:
PROC [s1, s2: RopePart, pos1:
INT ← 0, case:
BOOL ←
TRUE, clipBeforeSeek:
BOOL ←
FALSE]
RETURNS [
INT];
Like Rope.Index. clipBeforeSeek says it would be better to allocate a smaller rope than to search, in s1.base, past the end of the range relevent to s1.
Find: PROC [s1, s2: RopePart, pos1: INT ← 0, case: BOOL ← TRUE, clipBeforeSeek: BOOL ← FALSE] RETURNS [INT];
FindBackward:
PROC [s1, s2: RopePart, pos1:
INT ← MaxLen, case:
BOOL ←
TRUE, clipBeforeSeek:
BOOL ←
FALSE]
RETURNS [
INT];
IsEmpty:
PROC [RopePart]
RETURNS [
BOOL];
InlineIsEmpty:
PROC [r: RopePart]
RETURNS [
BOOL]
~ INLINE {RETURN[r.len = 0]};
Length:
PROC [base: RopePart]
RETURNS [
INT];
InlineLength:
PROC [base: RopePart]
RETURNS [
INT]
~ INLINE {RETURN[base.len]};
Size:
PROC [base: RopePart]
RETURNS [
INT];
Size[base] = Length[base]
InlineSize:
PROC [base: RopePart]
RETURNS [
INT]
~ INLINE {RETURN[base.len]};
Substr: PROC [base: RopePart, start: INT ← 0, len: INT ← MaxLen] RETURNS [RopePart];
Replace:
PROC [base: RopePart, start:
INT ← 0, len:
INT ← MaxLen, with: RopePart ← nil]
RETURNS [RopePart];
ReplaceElt:
PROC [base: RopePart, index:
INT, with:
CHAR]
RETURNS [RopePart];
Part 2: Extended operations and definitions
ActionType: TYPE ~ Rope.ActionType;
TranslatorType: TYPE ~ Rope.TranslatorType;
Run:
PROC [s1: RopePart, pos1:
INT ← 0, s2: RopePart, pos2:
INT ← 0, case:
BOOL ←
TRUE]
RETURNS [
INT];
IsPrefix: PROC [prefix, subject: RopePart, case: BOOL ← TRUE] RETURNS [BOOL];
IsSuffix:
PROC [suffix, subject: RopePart, case:
BOOL ←
TRUE]
RETURNS [
BOOL];
Match:
PROC [pattern, object: RopePart, case:
BOOL ←
TRUE]
RETURNS [
BOOL];
SkipTo: PROC [s: RopePart, pos: INT ← 0, skip: RopePart] RETURNS [INT];
SkipOver:
PROC [s: RopePart, pos:
INT ← 0, skip: RopePart]
RETURNS [
INT];
Map:
PROC [base: RopePart, action: ActionType]
RETURNS [
BOOL];
Translate:
PROC [base: RopePart, translator: TranslatorType ←
NIL]
RETURNS [RopePart];
ToRefText:
PROC [base: RopePart]
RETURNS [
REF
TEXT];
AppendChars:
PROC [to:
REF
TEXT, from: RopePart]
RETURNS [charsMoved:
NAT];
UnsafeMoveChars:
UNSAFE
PROC [to: Basics.UnsafeBlock, from: RopePart]
RETURNS [charsMoved:
INT];
Hash:
PROC [base: RopePart, case:
BOOL ←
TRUE, seed:
CARDINAL ← defaultSeed]
RETURNS [
CARDINAL];
defaultSeed: CARDINAL ~ 31415;