IPStackImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Doug Wyatt, May 30, 1985 5:52:34 pm PDT
DIRECTORY
IO USING [int, PutFR1],
IPInterpreter USING [Any, BoundsCheckInteger, Color, ColorFromAny, Context, Identifier, IdentifierFromAny, Integer, IntegerFromAny, IntegerFromNum, Marker, MasterError, maxInteger, nullMarker, Number, NumberFromAny, NumberRep, Operator, OperatorFromAny, Outline, OutlineFromAny, PixelArray, PixelArrayFromAny, RealFromAny, RealFromNum, Ref, StackArray, stackArraySize, StackList, StackMark, Trajectory, TrajectoryFromAny, Transformation, TransformationFromAny, Type, TypeCode, VEC, Vector, VectorFromAny];
IPStackImpl: CEDAR PROGRAM
IMPORTS IO, IPInterpreter
EXPORTS IPInterpreter
~ BEGIN OPEN IPInterpreter;
FlushStackArray: PROC[self: Ref] ~ {
FOR i: NAT IN[0..self.stackArrayCount) DO
val: Number ~ NEW[NumberRep ← self.stackArray[i]];
self.stackList ← CONS[val, self.stackList];
ENDLOOP;
self.stackArrayCount ← 0;
};
StackOverflow: PROC [self: Ref] ~ {
MasterError[code: $stackOverflow, explanation: IO.PutFR1[
"Stack overflow (maxStackLength=%g)", IO.int[self.stackCountMax]]];
};
StackUnderflow: PROC [self: Ref] ~ {
MasterError[code: $stackUnderflow, explanation: "Stack underflow"];
};
MarkMismatch: PROC [self: Ref] ~ {
MasterError[code: $markMismatch,
explanation: "Mark on stack does not match current context."];
};
PushAny: PUBLIC PROC[self: Ref, val: Any] ~ {
IF NOT self.stackCount<self.stackCountMax THEN StackOverflow[self];
IF NOT self.stackArrayCount=0 THEN FlushStackArray[self];
self.stackList ← CONS[val, self.stackList];
self.stackCount ← self.stackCount+1;
};
PushNum: PUBLIC PROC[self: Ref, val: NumberRep] ~ {
IF NOT self.stackCount<self.stackCountMax THEN StackOverflow[self];
IF NOT self.stackArrayCount<stackArraySize THEN FlushStackArray[self];
TRUSTED{ self.stackArray[self.stackArrayCount] ← val };
self.stackArrayCount ← self.stackArrayCount+1;
self.stackCount ← self.stackCount+1;
};
PushBool: PUBLIC PROC[self: Ref, val: BOOL] ~ {
PushInteger[self, IF val THEN 1 ELSE 0];
};
PushInteger: PUBLIC PROC[self: Ref, val: Integer] ~ {
n: NumberRep ~ [int[BoundsCheckInteger[val]]];
IF self.stackCount<self.stackCountMax AND self.stackArrayCount<stackArraySize THEN {
TRUSTED{ self.stackArray[self.stackArrayCount] ← n };
self.stackArrayCount ← self.stackArrayCount+1;
self.stackCount ← self.stackCount+1;
}
ELSE PushNum[self, n];
};
PushReal: PUBLIC PROC[self: Ref, val: REAL] ~ {
n: NumberRep ~ [real[val]];
IF self.stackCount<self.stackCountMax AND self.stackArrayCount<stackArraySize THEN {
TRUSTED{ self.stackArray[self.stackArrayCount] ← n };
self.stackArrayCount ← self.stackArrayCount+1;
self.stackCount ← self.stackCount+1;
}
ELSE PushNum[self, n];
};
PushVec: PUBLIC PROC[self: Ref, val: VEC] ~ {
PushReal[self, val.x]; PushReal[self, val.y];
};
PushIdentifier: PUBLIC PROC[self: Ref, val: Identifier] ~ {
IF val=NIL THEN MasterError[$nilFault, "Identifier value is NIL"];
PushAny[self, val];
};
PushVector: PUBLIC PROC[self: Ref, val: Vector] ~ {
IF val=NIL THEN MasterError[$nilFault, "Vector value is NIL"];
PushAny[self, val];
};
PushOperator: PUBLIC PROC[self: Ref, val: Operator] ~ {
IF val=NIL THEN MasterError[$nilFault, "Operator value is NIL"];
PushAny[self, val];
};
PushTransformation: PUBLIC PROC[self: Ref, val: Transformation] ~ {
IF val=NIL THEN MasterError[$nilFault, "Transformation value is NIL"];
PushAny[self, val];
};
PushPixelArray: PUBLIC PROC[self: Ref, val: PixelArray] ~ {
IF val=NIL THEN MasterError[$nilFault, "PixelArray value is NIL"];
PushAny[self, val];
};
PushColor: PUBLIC PROC[self: Ref, val: Color] ~ {
IF val=NIL THEN MasterError[$nilFault, "Color value is NIL"];
PushAny[self, val];
};
PushTrajectory: PUBLIC PROC[self: Ref, val: Trajectory] ~ {
IF val=NIL THEN MasterError[$nilFault, "Trajectory value is NIL"];
PushAny[self, val];
};
PushOutline: PUBLIC PROC[self: Ref, val: Outline] ~ {
IF val=NIL THEN MasterError[$nilFault, "Outline value is NIL"];
PushAny[self, val];
};
PopAny: PUBLIC PROC[self: Ref] RETURNS[Any] ~ {
IF NOT self.stackCount>0 THEN StackUnderflow[self];
self.stackCount ← self.stackCount-1;
IF self.stackArrayCount>0 THEN {
n: NumberRep ~ self.stackArray[self.stackArrayCount ← self.stackArrayCount-1];
RETURN[NEW[NumberRep ← n]];
}
ELSE { top: StackList ~ self.stackList; self.stackList ← top.rest; RETURN[top.first] };
};
PopNum: PUBLIC PROC[self: Ref] RETURNS[NumberRep] ~ {
IF self.stackCount>0 AND self.stackArrayCount>0 THEN {
n: NumberRep ~ self.stackArray[self.stackArrayCount ← self.stackArrayCount-1];
self.stackCount ← self.stackCount-1;
RETURN[n];
}
ELSE RETURN[NumberFromAny[PopAny[self]]^];
};
PopBool: PUBLIC PROC[self: Ref] RETURNS[BOOL] ~ {
RETURN[PopInteger[self]#0];
};
PopInteger: PUBLIC PROC[self: Ref] RETURNS[Integer] ~ {
IF self.stackCount>0 AND self.stackArrayCount>0 THEN {
n: NumberRep ~ self.stackArray[self.stackArrayCount ← self.stackArrayCount-1];
self.stackCount ← self.stackCount-1;
WITH n: n SELECT FROM
int => IF n.int IN[0..maxInteger] THEN RETURN[n.int];
ENDCASE;
RETURN[IntegerFromNum[n]];
}
ELSE RETURN[IntegerFromAny[PopAny[self]]];
};
PopReal: PUBLIC PROC[self: Ref] RETURNS[REAL] ~ {
IF self.stackCount>0 AND self.stackArrayCount>0 THEN {
n: NumberRep ~ self.stackArray[self.stackArrayCount ← self.stackArrayCount-1];
self.stackCount ← self.stackCount-1;
WITH n: n SELECT FROM
int => RETURN[REAL[n.int]];
real => RETURN[n.real];
ENDCASE;
RETURN[RealFromNum[n]];
}
ELSE RETURN[RealFromAny[PopAny[self]]];
};
PopVec: PUBLIC PROC[self: Ref] RETURNS[VEC] ~ {
y: REAL ~ PopReal[self]; x: REAL ~ PopReal[self]; RETURN[[x, y]];
};
PopIdentifier: PUBLIC PROC[self: Ref] RETURNS[Identifier] ~ {
x: Any ~ PopAny[self];
WITH x SELECT FROM x: Identifier => RETURN[x]; ENDCASE;
RETURN[IdentifierFromAny[x]];
};
PopVector: PUBLIC PROC[self: Ref] RETURNS[Vector] ~ {
x: Any ~ PopAny[self];
WITH x SELECT FROM x: Vector => RETURN[x]; ENDCASE;
RETURN[VectorFromAny[x]];
};
PopOperator: PUBLIC PROC[self: Ref] RETURNS[Operator] ~ {
x: Any ~ PopAny[self];
WITH x SELECT FROM x: Operator => RETURN[x]; ENDCASE;
RETURN[OperatorFromAny[x]];
};
PopTransformation: PUBLIC PROC[self: Ref] RETURNS[Transformation] ~ {
x: Any ~ PopAny[self];
WITH x SELECT FROM x: Transformation => RETURN[x]; ENDCASE;
RETURN[TransformationFromAny[x]];
};
PopPixelArray: PUBLIC PROC[self: Ref] RETURNS[PixelArray] ~ {
x: Any ~ PopAny[self];
WITH x SELECT FROM x: PixelArray => RETURN[x]; ENDCASE;
RETURN[PixelArrayFromAny[x]];
};
PopColor: PUBLIC PROC[self: Ref] RETURNS[Color] ~ {
x: Any ~ PopAny[self];
WITH x SELECT FROM x: Color => RETURN[x]; ENDCASE;
RETURN[ColorFromAny[x]];
};
PopTrajectory: PUBLIC PROC[self: Ref] RETURNS[Trajectory] ~ {
x: Any ~ PopAny[self];
WITH x SELECT FROM x: Trajectory => RETURN[x]; ENDCASE;
RETURN[TrajectoryFromAny[x]];
};
PopOutline: PUBLIC PROC[self: Ref] RETURNS[Outline] ~ {
x: Any ~ PopAny[self];
WITH x SELECT FROM x: Outline => RETURN[x]; ENDCASE;
RETURN[OutlineFromAny[x]];
};
Top: PUBLIC PROC[self: Ref] RETURNS[Any] ~ {
IF NOT self.stackCount>0 THEN MasterError[stackUnderflow];
IF self.stackArrayCount>0 THEN
RETURN[NEW[NumberRep ← self.stackArray[self.stackArrayCount-1]]]
ELSE RETURN[self.stackList.first];
};
TopType: PUBLIC PROC[self: Ref] RETURNS[TypeCode] ~ {
IF NOT self.stackCount>0 THEN StackUnderflow[self];
IF self.stackArrayCount>0 THEN RETURN[number]
ELSE RETURN[Type[self.stackList.first]];
};
Pop: PUBLIC PROC[self: Ref] ~ {
IF self.stackCount>0 AND self.stackArrayCount>0 THEN {
-- Avoid useless NEW[NumberRep].
self.stackCount ← self.stackCount-1;
self.stackArrayCount ← self.stackArrayCount-1;
}
ELSE [] ← PopAny[self];
};
Copy: PUBLIC PROC[self: Ref, depth: Integer] ~ {
IF NOT self.stackCount>=BoundsCheckInteger[depth] THEN StackUnderflow[self];
IF NOT (self.stackCountMax-self.stackCount)>=depth THEN StackOverflow[self];
IF depth=0 THEN RETURN;
IF self.stackArrayCount>=depth AND (stackArraySize-self.stackArrayCount)>=depth THEN {
n: NAT ~ depth;
b: NAT ~ self.stackArrayCount-n;
array: StackArray ~ self.stackArray;
FOR i: NAT IN[b..b+n) DO
TRUSTED{ array[i+n] ← array[i] };
ENDLOOP;
self.stackArrayCount ← self.stackArrayCount+n;
}
ELSE {
head, tail, each: StackList ← NIL;
IF NOT self.stackArrayCount=0 THEN FlushStackArray[self];
each ← self.stackList;
THROUGH [0..depth) DO
copy: StackList ~ CONS[each.first, NIL];
IF tail=NIL THEN head ← copy ELSE tail.rest ← copy;
tail ← copy; each ← each.rest;
ENDLOOP;
tail.rest ← self.stackList; self.stackList ← head;
};
self.stackCount ← self.stackCount+depth;
};
Roll: PUBLIC PROC[self: Ref, depth, moveFirst: Integer] ~ {
IF NOT BoundsCheckInteger[depth]>=BoundsCheckInteger[moveFirst] THEN MasterError[$invalidArgs, "ROLL: moveFirst exceeds depth"];
IF NOT self.stackCount>=depth THEN StackUnderflow[self];
IF depth=0 OR moveFirst=0 OR moveFirst=depth THEN RETURN;
IF self.stackArrayCount>=depth THEN {
n: NAT ~ depth;
m: NAT ~ moveFirst;
b: NAT ~ self.stackArrayCount-n;
a: StackArray ~ self.stackArray;
Reverse: PROC[bot, top: NAT] ~ { -- reverse a[bot..top)
FOR x: NAT IN[0..NAT[top-bot]/2) DO
i: NAT ~ bot+x; j: NAT ~ top-1-x;
temp: NumberRep ~ a[i];
TRUSTED{ a[i] ← a[j] };
TRUSTED{ a[j] ← temp };
ENDLOOP;
};
Reverse[b, b+m]; Reverse[b+m, b+n]; Reverse[b, b+n];
}
ELSE {
k: Integer ~ depth-moveFirst;
top, kth, nth, each: StackList ← NIL;
IF NOT self.stackArrayCount=0 THEN FlushStackArray[self];
each ← top ← self.stackList;
THROUGH [0..k) DO kth ← each; each ← each.rest ENDLOOP;
self.stackList ← each; -- new top of stack
THROUGH [k..depth) DO nth ← each; each ← each.rest ENDLOOP;
kth.rest ← each; nth.rest ← top;
};
};
Mark: PUBLIC PROC[self: Ref, n: Integer] ~ {
contextMarker: Marker ~ IF self.context=NIL THEN nullMarker ELSE self.context.marker;
mark: StackMark ← [];
IF NOT self.stackCount>=BoundsCheckInteger[n] THEN StackUnderflow[self];
mark.count ← self.stackCount-n; -- number of elements hidden by the mark
mark.marker ← contextMarker; -- marker for current context
self.stackCount ← self.stackCount-mark.count; -- = n
self.stackCountMax ← self.stackCountMax-mark.count;
self.stackMarkList ← CONS[mark, self.stackMarkList];
};
Unmark: PUBLIC PROC[self: Ref, n: Integer] ~ {
contextMarker: Marker ~ IF self.context=NIL THEN nullMarker ELSE self.context.marker;
mark: StackMark ~ IF self.stackMarkList=NIL THEN [] ELSE self.stackMarkList.first;
IF NOT mark.marker=contextMarker THEN MarkMismatch[self];
IF NOT self.stackCount>=BoundsCheckInteger[n] THEN StackUnderflow[self];
IF NOT self.stackCount=n THEN MasterError[$unmarkFailed,
"UNMARK found no mark at the specified depth"];
self.stackCount ← self.stackCount+mark.count;
self.stackCountMax ← self.stackCountMax+mark.count;
self.stackMarkList ← self.stackMarkList.rest;
};
Count: PUBLIC PROC[self: Ref] RETURNS[Integer] ~ {
contextMarker: Marker ~ IF self.context=NIL THEN nullMarker ELSE self.context.marker;
mark: StackMark ~ IF self.stackMarkList=NIL THEN [] ELSE self.stackMarkList.first;
IF NOT mark.marker=contextMarker THEN MarkMismatch[self];
RETURN[BoundsCheckInteger[self.stackCount]];
};
PopToActiveMark: PUBLIC PROC[self: Ref] RETURNS[Marker] ~ {
DO mark: StackMark ~ self.stackMarkList.first;
WHILE self.stackCount>0 DO Pop[self] ENDLOOP;
IF mark.marker=nullMarker THEN RETURN[mark.marker];
FOR context: Context ← self.context, context.caller UNTIL context=NIL DO
IF context.marker=mark.marker THEN RETURN[mark.marker]; -- context still exists
ENDLOOP;
self.stackCount ← self.stackCount+mark.count;
self.stackCountMax ← self.stackCountMax+mark.count;
self.stackMarkList ← self.stackMarkList.rest;
ENDLOOP;
};
END.