PSStackImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Doug Wyatt, May 8, 1987 2:37:48 pm PDT
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];
};
Primitives
Ppop:
PROC [self: Root] ~ {
[] ← PopAny[self];
};
Pexch:
PROC [self: Root] ~ {
Roll[self, 2, 1];
};
Pdup:
PROC [self: Root] ~ {
Copy[self, 2];
};
Pindex:
PROC [self: Root] ~ {
n: INT ~ PopInt[self];
PushAny[self, Index[self, n]];
};
Proll:
PROC [self: Root] ~ {
j: INT ~ PopInt[self];
n: INT ~ PopInt[self];
Roll[self, n, j];
};
Pclear:
PROC [self: Root] ~ {
Clear[self];
};
Pcount:
PROC [self: Root] ~ {
PushInt[self, Count[self]];
};
Pmark:
PROC [self: Root] ~ {
PushMark[self];
};
Pcleartomark:
PROC [self: Root] ~ {
ClearToMark[self];
};
Pcounttomark:
PROC [self: Root] ~ {
PushInt[self, CountToMark[self]];
};
StackPrimitives:
PROC [self: Root] ~ {
Register[self, "pop", Ppop];
Register[self, "exch", Pexch];
Register[self, "dup", Pdup];
Register[self, "index", Pindex];
Register[self, "roll", Proll];
Register[self, "clear", Pclear];
Register[self, "count", Pcount];
Register[self, "mark", Pmark];
Register[self, "cleartomark", Pcleartomark];
Register[self, "counttomark", Pcounttomark];
};
RegisterPrimitives[StackPrimitives];