PSStackImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Doug Wyatt, May 13, 1987 10:59:39 am PDT
PostScript implementation: stack operations.
DIRECTORY
PS;
PSStackImpl: CEDAR PROGRAM
IMPORTS PS
EXPORTS PS
~ BEGIN OPEN PS;
Basic stack operations
Stack: TYPE ~ REF StackRep;
StackRep: PUBLIC TYPE ~ RECORD [
count: ArrayIndex,
size: ArrayIndex,
array: ArrayRef
];
PushAny: PUBLIC PROC [self: Root, x: Any] ~ {
stack: Stack ~ self.stack;
IF NOT stack.count<stack.size THEN ERROR Error[stackoverflow];
stack.array[stack.count] ← x;
stack.count ← stack.count+1;
};
PopAny: PUBLIC PROC [self: Root] RETURNS [x: Any] ~ {
stack: Stack ~ self.stack;
IF NOT stack.count>0 THEN ERROR Error[stackunderflow];
stack.count ← stack.count-1;
RETURN [stack.array[stack.count]];
};
Top: PUBLIC PROC [self: Root] RETURNS [Any] ~ {
stack: Stack ~ self.stack;
IF NOT stack.count>0 THEN ERROR Error[stackunderflow];
RETURN [stack.array[stack.count-1]];
};
TopType: PUBLIC PROC [self: Root] RETURNS [TypeCode] ~ {
stack: Stack ~ self.stack;
IF NOT stack.count>0 THEN ERROR Error[stackunderflow];
RETURN [stack.array[stack.count-1].val.type];
};
Copy: PUBLIC PROC [self: Root, n: INT] ~ {
stack: Stack ~ self.stack;
IF n<0 THEN ERROR Error[rangecheck];
IF n>stack.count THEN ERROR Error[stackunderflow];
IF n>(stack.size-stack.count) THEN ERROR Error[stackoverflow];
FOR i: ArrayIndex IN [stack.count..ArrayIndex[stack.count+n]) DO
stack.array[i] ← stack.array[i-n];
ENDLOOP;
stack.count ← stack.count+n;
};
Reverse: PROC [array: ArrayRef, m1, m2: ArrayIndex] ~ {
FOR i: ArrayIndex IN[0..(m2-m1)/2) DO
i1: ArrayIndex ~ m1+i;
i2: ArrayIndex ~ m2-1-i;
x1: Any ~ array[i1];
x2: Any ~ array[i2];
array[i1] ← x2;
array[i2] ← x1;
ENDLOOP;
};
Roll: PUBLIC PROC [self: Root, n, j: INT] ~ {
stack: Stack ~ self.stack;
IF n<0 THEN ERROR Error[rangecheck];
IF n>stack.count THEN ERROR Error[stackunderflow];
IF j NOT IN [0..n) THEN { j ← j MOD n; IF j<0 THEN j ← j+n };
IF j#0 THEN {
k3: ArrayIndex ~ stack.count;
k2: ArrayIndex ~ k3-j;
k1: ArrayIndex ~ k3-n;
Reverse[stack.array, k1, k2];
Reverse[stack.array, k2, k3];
Reverse[stack.array, k1, k3];
};
};
Index: PUBLIC PROC [self: Root, n: INT] RETURNS [Any] ~ {
stack: Stack ~ self.stack;
IF n<0 THEN ERROR Error[rangecheck];
IF NOT n<stack.count THEN ERROR Error[stackunderflow];
RETURN [stack.array[stack.count-1-n]];
};
Clear: PUBLIC PROC [self: Root] ~ {
stack: Stack ~ self.stack;
FOR i: ArrayIndex IN[0..stack.count) DO stack.array[i].ref ← NIL ENDLOOP;
stack.count ← 0;
};
Count: PUBLIC PROC [self: Root] RETURNS [INT] ~ {
stack: Stack ~ self.stack;
RETURN [stack.count];
};
RestoreCount: PUBLIC PROC [self: Root, n: INT] ~ {
stack: Stack ~ self.stack;
stack.count ← n;
};
ClearToMark: PUBLIC PROC [self: Root] ~ {
stack: Stack ~ self.stack;
FOR i: ArrayIndex DECREASING IN [0..stack.count) DO
IF stack.array[i].val.type=mark THEN { stack.count ← i; RETURN };
ENDLOOP;
ERROR Error[unmatchedmark];
};
CountToMark: PUBLIC PROC [self: Root] RETURNS [INT] ~ {
stack: Stack ~ self.stack;
IF stack.count>0 THEN {
last: ArrayIndex ~ stack.count-1;
FOR i: ArrayIndex DECREASING IN [0..last] DO
IF stack.array[i].val.type=mark THEN RETURN [last-i];
ENDLOOP;
};
ERROR Error[unmatchedmark];
};
Convenience operations
PushInt: PUBLIC PROC [self: Root, int: INT] ~ {
PushAny[self, [val: [executable: FALSE, variant: integer[int: int]], ref: NIL]];
};
PushReal: PUBLIC PROC [self: Root, real: REAL] ~ {
PushAny[self, [val: [executable: FALSE, variant: real[real: real]], ref: NIL]];
};
PushBool: PUBLIC PROC [self: Root, bool: BOOL] ~ {
PushAny[self, [val: [executable: FALSE, variant: boolean[bool: bool]], ref: NIL]];
};
PushArray: PUBLIC PROC [self: Root, array: Array] ~ {
PushAny[self, AnyFromArray[array]];
};
PushString: PUBLIC PROC [self: Root, string: String] ~ {
PushAny[self, AnyFromString[string]];
};
PushFile: PUBLIC PROC [self: Root, file: File] ~ {
PushAny[self, AnyFromFile[file]];
};
PushDict: PUBLIC PROC [self: Root, dict: Dict] ~ {
PushAny[self, AnyFromDict[dict]];
};
PushName: PUBLIC PROC [self: Root, name: Name] ~ {
PushAny[self, AnyFromName[name]];
};
PopInt: PUBLIC PROC [self: Root] RETURNS [INT] ~ {
x: Any ~ PopAny[self];
WITH v: x.val SELECT FROM
integer => RETURN [v.int];
ENDCASE => RETURN [IntFromAny[x]];
};
PopReal: PUBLIC PROC [self: Root] RETURNS [REAL] ~ {
x: Any ~ PopAny[self];
WITH v: x.val SELECT FROM
integer => RETURN [REAL[v.int]];
real => RETURN [v.real];
ENDCASE => RETURN [RealFromAny[x]];
};
PopBool: PUBLIC PROC [self: Root] RETURNS [BOOL] ~ {
x: Any ~ PopAny[self];
WITH v: x.val SELECT FROM
boolean => RETURN [v.bool];
ENDCASE => RETURN [BoolFromAny[x]];
};
PopNum: PUBLIC PROC [self: Root] RETURNS [Num] ~ {
x: Any ~ PopAny[self];
WITH v: x.val SELECT FROM
integer => RETURN [[int[v.int]]];
real => RETURN [[real[v.real]]];
ENDCASE => ERROR Error[typecheck];
};
PopArray: PUBLIC PROC [self: Root] RETURNS [Array] ~ {
RETURN[ArrayFromAny[PopAny[self]]];
};
PopString: PUBLIC PROC [self: Root] RETURNS [String] ~ {
RETURN[StringFromAny[PopAny[self]]];
};
PopFile: PUBLIC PROC [self: Root] RETURNS [File] ~ {
RETURN[FileFromAny[PopAny[self]]];
};
PopDict: PUBLIC PROC [self: Root] RETURNS [Dict] ~ {
RETURN[DictFromAny[PopAny[self]]];
};
PushMark: PUBLIC PROC [self: Root] ~ {
PushAny[self, [val: [executable: FALSE, variant: mark[]], ref: NIL]];
};
PopMark: PUBLIC PROC [self: Root] ~ {
x: Any ~ PopAny[self];
WITH v: x.val SELECT FROM
mark => NULL;
ENDCASE => ERROR Error[typecheck];
};
END.