-- RopeInline.mesa
-- Russ Atkinson, August 30, 1982 1:45 pm

DIRECTORY
Mopcodes USING
[zAND, zBNDCK, zDADD, zLI0, zLI1, zLINB, zLINI,
zNEG, zPOP, zRSTRL, zWSTRL],
Rope;

RopeInline: CEDAR DEFINITIONS
IMPORTS Rope
SHARES Rope
= BEGIN OPEN Mopcodes, Rope;

FirstPtr: TYPE = LONG POINTER TO INTEGER;
Node: TYPE = REF Node;
NodeRep: TYPE = node RopeRep;

Ttext: TYPE = text RopeRep;
Tsubstr: TYPE = substr node RopeRep;
Tconcat: TYPE = concat node RopeRep;
Treplace: TYPE = replace node RopeRep;
Tobject: TYPE = object node RopeRep;

MaxDepth: CARDINAL = 40;

Pair: TYPE = MACHINE DEPENDENT RECORD [low: CARDINAL, high: INTEGER];

HighPart: PROC [x: INT] RETURNS [INTEGER] = INLINE {TRUSTED {
RETURN [LOOPHOLE[x, Pair].high]}};

LowPart: PROC [x: INT] RETURNS [CARDINAL] = INLINE {TRUSTED {
RETURN [LOOPHOLE[x, Pair].low]}};

QShort: PROC [x: INT] RETURNS [CARDINAL] = INLINE {TRUSTED {
RETURN [LOOPHOLE[x, Pair].low]}};

RoundToFit: PROC [n: NAT] RETURNS [NAT] = TRUSTED MACHINE CODE {
zNEG; zLINB, 370B; zAND; zNEG};

BoundsFault: PROC = TRUSTED MACHINE CODE {
zLI1; zLI0; zBNDCK};

NonNeg: PROC [x: INT] RETURNS [INT] = TRUSTED MACHINE CODE {
zLINI; zBNDCK;};

Short: PROC [x: INT] RETURNS [CARDINAL] = TRUSTED MACHINE CODE {
zLI1; zBNDCK; zPOP; zLINI; zBNDCK;};

CheckLongAdd: PROC [x,y: INT] RETURNS [INT] = TRUSTED MACHINE CODE {
zDADD; zLINI; zBNDCK;};

ExtendPositive: PROC [x: INTEGER] RETURNS [INT] = TRUSTED MACHINE CODE {
zLI0};

NewText: PROC [size: NAT] RETURNS [Text];
-- here for compatibility, no longer an INLINE

InlineFetch: PROC [base: ROPE, index: INT] RETURNS [c: CHAR] = INLINE {TRUSTED {
IF base # NIL THEN
{first: INTEGERLOOPHOLE[base, FirstPtr]^;
IF first > 0 AND index < first THEN
RETURN [QFetch[LOOPHOLE[base, Text], LowPart[index]]]};
RETURN [Rope.Fetch[base, index]]}};

InlineSize: PROC [base: ROPE] RETURNS [INT] = INLINE {TRUSTED {
IF base = NIL THEN RETURN [0];
{first: INTEGERLOOPHOLE[base, FirstPtr]^;
IF first >= 0 THEN RETURN [ExtendPositive[first]]};
RETURN [LOOPHOLE[base, REF Tobject].size];
}};

IsEmpty: PROC [base: ROPE] RETURNS [BOOL] = INLINE {TRUSTED {
IF base = NIL THEN RETURN [TRUE];
{first: INTEGERLOOPHOLE[base, FirstPtr]^;
IF first >= 0 THEN RETURN [first = 0]};
RETURN [LOOPHOLE[base, REF Tobject].size = 0];
}};

SingleSize: PROC [base: ROPE] RETURNS [INT,Text] = INLINE {TRUSTED {
IF base = NIL THEN RETURN [0, NIL];
{first: INTEGERLOOPHOLE[base, FirstPtr]^;
IF first >= 0 THEN RETURN [ExtendPositive[first], LOOPHOLE[base]]};
RETURN [LOOPHOLE[base, REF Tobject].size, NIL];
}};

DoubleSize: PROC [r1,r2: ROPE] RETURNS [s1: INT, s2: INT, both: BOOL] = INLINE {TRUSTED {
t1,t2: Text;
[s1,t1] ← SingleSize[r1];
[s2,t2] ← SingleSize[r2];
both ← t1 # NIL AND t2 # NIL;
}};

Lower: PROC [c: CHAR] RETURNS [CHAR] = INLINE
{RETURN [IF c IN ['A .. 'Z] THEN c+40B ELSE c]};

InlineDepth: PROC [r: ROPE] RETURNS [INTEGER] = INLINE {TRUSTED {
IF r = NIL THEN RETURN [0];
WITH r: r SELECT FROM
node =>
WITH x: r SELECT FROM
  substr =>
{RETURN [x.depth]};
concat =>
{RETURN [x.depth]};
replace =>
{RETURN [x.depth]};
ENDCASE;
ENDCASE;
RETURN [1]}};

InlineFlatten: PROC [r: ROPE] RETURNS [Text] = INLINE {TRUSTED {
IF r = NIL THEN RETURN [NIL];
IF LOOPHOLE[r, FirstPtr]^ >= 0 THEN RETURN [LOOPHOLE[r]];
RETURN [Rope.Flatten[r]]}};

-- the unsafe procs follow

QFetch: UNSAFE PROC
[base: Text, index: CARDINAL] RETURNS [CHAR] = UNCHECKED MACHINE CODE {
-- quick fetch using the index, no NIL or bounds checking
zRSTRL, 4};

QStore: UNSAFE PROC [c: CHAR, base: Text, index: CARDINAL] = UNCHECKED MACHINE CODE {
-- quick store into string for hack purposes, no NIL or bounds check
zWSTRL, 4};

END.