TiogaRopesImpl.mesa
Mike Spreitzer August 5, 1986 4:26:06 pm PDT
DIRECTORY Rope, RuntimeError, TextNode, TiogaRopes;
TiogaRopesImpl:
CEDAR
PROGRAM
IMPORTS Rope, RuntimeError, TextNode
EXPORTS TiogaRopes
=
BEGIN OPEN TiogaRopes;
Location: TYPE = TextNode.Location;
TiogaRope: TYPE = REF TiogaRopePrivate;
TiogaRopePrivate:
TYPE =
RECORD [
node: Node,
start, length: INT,
skipCommentNode: BOOL,
curNode: Node ← NIL,
curNodeStart, curNodeLength: INT ← 0,
curRope: ROPE
];
RopeFromTioga:
PUBLIC
PROC [node: Node, start:
INT ← 0, length:
INT ←
LAST[
INT], skipCommentNode:
BOOL ←
FALSE]
RETURNS [asRope:
ROPE] = {
end: Location = DocEnd[node, skipCommentNode];
nodeLoc: Location = [node, 0];
remSize: INT = TextNode.LocOffset[nodeLoc, end, 1, skipCommentNode];
IF start >= remSize THEN RETURN [NIL];
{curRope: ROPE = node.NodeRope[];
tr: TiogaRope =
NEW [TiogaRopePrivate ← [
node: node,
start: start,
length: MIN[length, remSize - start],
skipCommentNode: skipCommentNode,
curNode: node,
curNodeStart: 0,
curNodeLength: curRope.Length[],
curRope: curRope
]];
asRope ← Rope.MakeRope[tr, tr.length, FetchFromTiogaRope];
}};
JumpTo:
PROC [tr: TiogaRope, index:
INT] = {
newOffset: INT = tr.start+index;
here: Location = IF newOffset >= tr.curNodeStart/2 THEN LocRelative[[tr.curNode, 0], newOffset-tr.curNodeStart, 1, tr.skipCommentNode] ELSE LocRelative[[tr.node, 0], newOffset, 1, tr.skipCommentNode];
tr.curNode ← here.node;
tr.curNodeStart ← newOffset - here.where;
tr.curRope ← TextNode.NodeRope[tr.curNode];
tr.curNodeLength ← tr.curRope.Length[];
};
LocRelative:
PROC [location: Location, count:
INT,
break:
NAT ← 1, skipCommentNodes:
BOOL ←
FALSE]
RETURNS [rel: Location] = {
SELECT count
FROM
=0 => rel ← location --avoid the bogosity in TextNodeImpl.LocRelative--;
>0 => rel ← TextNode.LocRelative[location, count, break, skipCommentNodes];
<0 => {
--TextNodeImpl.LocRelative won't backup over node boundaries
backParent: Node ← NIL;
rel ← location;
WHILE count + rel.where < 0
DO
count ← count + rel.where;
[rel.node, backParent, ] ← TextNode.Backward[rel.node, backParent];
rel.where ← IF (NOT skipCommentNodes) OR (NOT rel.node.comment) THEN rel.node.rope.Length[] + break ELSE 0;
ENDLOOP;
rel.where ← count + rel.where;
};
ENDCASE => ERROR;
rel ← rel;
};
FetchFromTiogaRope:
PROC [data:
REF, index:
INT]
RETURNS [char:
CHAR]
--Rope.FetchType-- = {
tr: TiogaRope = NARROW[data];
IF NOT index IN [0 .. tr.length) THEN ERROR RuntimeError.BoundsFault;
IF NOT index+tr.start - tr.curNodeStart IN [0 .. tr.curNodeLength] THEN JumpTo[tr, index];
index ← index+tr.start - tr.curNodeStart;
char ← IF index < tr.curNodeLength THEN tr.curRope.Fetch[index] ELSE '\n;
};
DocEnd:
PROC [node: Node, skipCommentNode:
BOOL]
RETURNS [endLoc: Location] = {
endNode: Node ← TextNode.Root[node];
IF endNode = NIL THEN ERROR;
DO
next: Node ← TextNode.LastChild[endNode];
IF next = NIL THEN EXIT;
endNode ← next;
ENDLOOP;
IF skipCommentNode THEN WHILE endNode.comment DO endNode ← TextNode.StepBackward[endNode] ENDLOOP;
endLoc ← [endNode, TextNode.NodeRope[endNode].Length[]+1];
};
END.