JaMStackImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Doug Wyatt, March 18, 1985 3:31:31 pm PST
Stone, December 4, 1985 10:23:44 am PST
DIRECTORY
JaM,
JaMPrimitives,
Real;
JaMStackImpl: CEDAR PROGRAM
IMPORTS JaM, Real
EXPORTS JaM, JaMPrimitives
~ BEGIN OPEN JaM;
NumberRep: TYPE ~ RECORD[
SELECT tag: * FROM
int => [int: INT],
real => [real: REAL],
ENDCASE
];
AnyFromNum: PROC[n: NumberRep] RETURNS[Any] ~ {
WITH n: n SELECT FROM
int => RETURN[NEW[INT ← n.int]];
real => RETURN[NEW[REAL ← n.real]];
ENDCASE => ERROR;
};
NumFromAny: PROC[x: Any] RETURNS[NumberRep] ~ {
WITH x SELECT FROM
x: REF INT => RETURN[[int[x^]]];
x: REF REAL => RETURN[[real[x^]]];
ENDCASE => ERROR Error[WrongType];
};
firstInt: REALINT.FIRST;
lastInt: REALINT.LAST;
IntFromReal: PROC[r: REAL] RETURNS[INT] ~ {
i: INT ← 0;
IF r IN[firstInt..lastInt] THEN i ← Real.Fix[r];
IF i=r THEN RETURN[i];
ERROR Error[WrongType];
};
IntFromNum: PROC[n: NumberRep] RETURNS[INT] ~ {
WITH n: n SELECT FROM
int => RETURN[n.int];
real => RETURN[IntFromReal[n.real]];
ENDCASE => ERROR;
};
IntFromAny: PROC[x: Any] RETURNS[INT] ~ {
WITH x SELECT FROM
x: REF INT => RETURN[x^];
x: REF REAL => RETURN[IntFromReal[x^]];
ENDCASE => ERROR Error[WrongType];
};
RealFromNum: PROC[n: NumberRep] RETURNS[REAL] ~ {
WITH n: n SELECT FROM
int => RETURN[REAL[n.int]];
real => RETURN[n.real];
ENDCASE => ERROR;
};
RealFromAny: PROC[x: Any] RETURNS[REAL] ~ {
WITH x SELECT FROM
x: REF INT => RETURN[REAL[x^]];
x: REF REAL => RETURN[x^];
ENDCASE => ERROR Error[WrongType];
};
arraySize: NAT ~ 8;
StackArray: TYPE ~ REF StackArrayRep;
StackArrayRep: TYPE ~ ARRAY[0..arraySize) OF NumberRep;
StackList: TYPE ~ LIST OF Any;
Stack: TYPE ~ REF StackRep;
StackRep: PUBLIC TYPE ~ RECORD[
array: StackArray ← NIL, -- a few numbers on top of the stack
arrayCount: [0..arraySize] ← 0, -- number of elements in array
list: StackList ← NIL, -- the rest of the stack
count: INT ← 0, -- number of stack elements above the top mark
countMax: INT ← 0 -- maximum count permitted above the top mark
];
NewStack: PUBLIC PROC RETURNS[Stack] ~ {
stack: Stack ~ NEW[StackRep ← []];
stack.array ← NEW[StackArrayRep];
stack.countMax ← LAST[INTEGER];
RETURN[stack];
};
FlushStackArray: PROC[stack: Stack] ~ {
FOR i: NAT IN[0..stack.arrayCount) DO
n: NumberRep ~ stack.array[i];
stack.list ← CONS[AnyFromNum[n], stack.list];
ENDLOOP;
stack.arrayCount ← 0;
};
Push: PUBLIC PROC[self: State, x: Any] ~ {
stack: Stack ~ self.stack;
IF NOT stack.count<stack.countMax THEN ERROR Error[StackOverflow];
IF NOT stack.arrayCount=0 THEN FlushStackArray[stack];
stack.list ← CONS[x, stack.list];
stack.count ← stack.count+1;
};
PushNum: PROC[self: State, x: NumberRep] ~ {
stack: Stack ~ self.stack;
IF NOT stack.count<stack.countMax THEN ERROR Error[StackOverflow];
IF NOT stack.arrayCount<arraySize THEN FlushStackArray[stack];
TRUSTED{ stack.array[stack.arrayCount] ← x };
stack.arrayCount ← stack.arrayCount+1;
stack.count ← stack.count+1;
};
PushBool: PUBLIC PROC[self: State, x: BOOL] ~ {
PushInt[self, IF x THEN 1 ELSE 0];
};
PushInt: PUBLIC PROC[self: State, x: INT] ~ {
stack: Stack ~ self.stack;
n: NumberRep ~ [int[x]];
IF stack.count<stack.countMax AND stack.arrayCount<arraySize THEN {
TRUSTED{ stack.array[stack.arrayCount] ← n };
stack.arrayCount ← stack.arrayCount+1;
stack.count ← stack.count+1;
}
ELSE PushNum[self, n];
};
PushReal: PUBLIC PROC[self: State, x: REAL] ~ {
stack: Stack ~ self.stack;
n: NumberRep ~ [real[x]];
IF stack.count<stack.countMax AND stack.arrayCount<arraySize THEN {
TRUSTED{ stack.array[stack.arrayCount] ← n };
stack.arrayCount ← stack.arrayCount+1;
stack.count ← stack.count+1;
}
ELSE PushNum[self, n];
};
Pop: PUBLIC PROC[self: State] RETURNS[Any] ~ {
stack: Stack ~ self.stack;
IF NOT stack.count>0 THEN ERROR Error[StackUnderflow];
stack.count ← stack.count-1;
IF stack.arrayCount>0 THEN {
n: NumberRep ~ stack.array[stack.arrayCount ← stack.arrayCount-1];
RETURN[AnyFromNum[n]];
}
ELSE { top: StackList ~ stack.list; stack.list ← top.rest; RETURN[top.first] };
};
PopNum: PROC[self: State] RETURNS[NumberRep] ~ {
stack: Stack ~ self.stack;
IF stack.count>0 AND stack.arrayCount>0 THEN {
n: NumberRep ~ stack.array[stack.arrayCount ← stack.arrayCount-1];
stack.count ← stack.count-1;
RETURN[n];
}
ELSE RETURN[NumFromAny[Pop[self]]];
};
PopBool: PUBLIC PROC[self: State] RETURNS[BOOL] ~ {
RETURN[PopInt[self]#0];
};
PopInt: PUBLIC PROC[self: State] RETURNS[INT] ~ {
stack: Stack ~ self.stack;
IF stack.count>0 AND stack.arrayCount>0 THEN {
n: NumberRep ~ stack.array[stack.arrayCount ← stack.arrayCount-1];
stack.count ← stack.count-1;
WITH n: n SELECT FROM
int => RETURN[n.int];
ENDCASE;
RETURN[IntFromNum[n]];
}
ELSE RETURN[IntFromAny[Pop[self]]];
};
PopReal: PUBLIC PROC[self: State] RETURNS[REAL] ~ {
stack: Stack ~ self.stack;
IF stack.count>0 AND stack.arrayCount>0 THEN {
n: NumberRep ~ stack.array[stack.arrayCount ← stack.arrayCount-1];
stack.count ← stack.count-1;
WITH n: n SELECT FROM
int => RETURN[REAL[n.int]];
real => RETURN[n.real];
ENDCASE;
RETURN[RealFromNum[n]];
}
ELSE RETURN[RealFromAny[Pop[self]]];
};
PopRope: PUBLIC PROC[self: State] RETURNS[ROPE] ~ {
x: Any ~ Pop[self];
WITH x SELECT FROM
x: ROPE => RETURN[x];
x: ATOM => RETURN[AtomToRope[x]];
ENDCASE => ERROR Error[WrongType];
};
PopStream: PUBLIC PROC[self: State] RETURNS[STREAM] ~ {
x: Any ~ Pop[self];
WITH x SELECT FROM
x: STREAM => RETURN[x];
ENDCASE => ERROR Error[WrongType];
};
PopArray: PUBLIC PROC[self: State] RETURNS[Array] ~ {
x: Any ~ Pop[self];
WITH x SELECT FROM
x: Array => RETURN[x];
ENDCASE => ERROR Error[WrongType];
};
PopDict: PUBLIC PROC[self: State] RETURNS[Dict] ~ {
x: Any ~ Pop[self];
WITH x SELECT FROM
x: Dict => RETURN[x];
ENDCASE => ERROR Error[WrongType];
};
Copy: PUBLIC PROC[self: State, n: INT] ~ {
stack: Stack ~ self.stack;
IF n<0 THEN ERROR Error[InvalidArgs];
IF NOT stack.count>=n THEN ERROR Error[StackUnderflow];
IF NOT (stack.countMax-stack.count)>=n THEN ERROR Error[StackOverflow];
IF n=0 THEN RETURN;
IF stack.arrayCount>=n AND (arraySize-stack.arrayCount)>=n THEN {
k: NAT ~ n;
b: NAT ~ stack.arrayCount-k;
array: StackArray ~ stack.array;
FOR i: NAT IN[b..b+k) DO TRUSTED{ array[i+k] ← array[i] } ENDLOOP;
stack.arrayCount ← stack.arrayCount+k;
}
ELSE {
head, tail, each: StackList ← NIL;
IF NOT stack.arrayCount=0 THEN FlushStackArray[stack];
each ← stack.list;
THROUGH [0..n) 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 ← stack.list; stack.list ← head;
};
stack.count ← stack.count+n;
};
Roll: PUBLIC PROC[self: State, n, k: INT] ~ {
stack: Stack ~ self.stack;
IF k<0 THEN k ← n+k;
IF n<0 OR k<0 OR k>n THEN ERROR Error[InvalidArgs];
IF n>stack.count THEN ERROR Error[StackUnderflow];
IF n=0 OR k=0 OR k=n THEN RETURN;
IF stack.arrayCount>=n THEN {
m: INT ~ n-k;
b: INT ~ stack.arrayCount-n;
a: StackArray ~ stack.array;
Reverse: PROC[bot, top: INT] ~ { -- 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 {
top, kth, nth, each: StackList ← NIL;
IF NOT stack.arrayCount=0 THEN FlushStackArray[stack];
each ← top ← stack.list;
THROUGH [0..k) DO kth ← each; each ← each.rest ENDLOOP;
stack.list ← each; -- new top of stack
THROUGH [k..n) DO nth ← each; each ← each.rest ENDLOOP;
kth.rest ← each; nth.rest ← top;
};
};
Count: PUBLIC PROC[self: State] RETURNS[INT] ~ {
stack: Stack ~ self.stack;
RETURN[stack.count];
};
Index: PUBLIC PROC[self: State, i: INT] RETURNS[Any] ~ {
stack: Stack ~ self.stack;
ERROR Error[Unimplemented];
};
PushMark: PUBLIC PROC[self: State, m: INT ← 0] ~ {
Push[self, NEW[MarkRep ← [m]]];
};
PopMark: PUBLIC PROC[self: State, m: INT ← 0] ~ {
WITH Pop[self] SELECT FROM
x: Mark => IF x.m#m THEN ERROR Error[WrongMark];
ENDCASE => ERROR Error[WrongType];
};
CountToMark: PUBLIC PROC[self: State, m: INT ← 0] RETURNS[INT] ~ {
stack: Stack ~ self.stack;
list: StackList ← stack.list;
FOR i: INT IN[stack.arrayCount..stack.count) DO
WITH list.first SELECT FROM
x: Mark => IF x.m=m THEN RETURN[i] ELSE ERROR Error[WrongMark];
ENDCASE;
list ← list.rest;
ENDLOOP;
RETURN[stack.count];
};
ApplyPop: PUBLIC PROC[self: State] ~ {
stack: Stack ~ self.stack;
IF stack.count>0 AND stack.arrayCount>0 THEN { -- Avoid useless NEW
stack.count ← stack.count-1;
stack.arrayCount ← stack.arrayCount-1;
}
ELSE [] ← Pop[self];
};
ApplyCopy: PUBLIC PROC[self: State] ~ {
n: INT ~ PopInt[self];
Copy[self, n];
};
ApplyDup: PUBLIC PROC[self: State] ~ {
Copy[self, 1];
};
ApplyRoll: PUBLIC PROC[self: State] ~ {
k: INT ~ PopInt[self];
n: INT ~ PopInt[self];
Roll[self, n, k];
};
ApplyExch: PUBLIC PROC[self: State] ~ {
Roll[self, 2, 1];
};
ApplyCount: PUBLIC PROC[self: State] ~ {
n: INT ~ Count[self];
PushInt[self, n];
};
ApplyIndex: PUBLIC PROC[self: State] ~ {
i: INT ~ Count[self];
Push[self, Index[self, i]];
};
ApplyMark: PUBLIC PROC[self: State] ~ {
PushMark[self];
};
ApplyCountToMark: PUBLIC PROC[self: State] ~ {
n: INT ~ CountToMark[self];
PushInt[self, n];
};
END.